xref: /onnv-gate/usr/src/cmd/dtrace/test/cmd/scripts/dtest.pl (revision 8287:771477e4b843)
12633Sahl#!/usr/perl5/bin/perl
22633Sahl#
32633Sahl# CDDL HEADER START
42633Sahl#
52633Sahl# The contents of this file are subject to the terms of the
62633Sahl# Common Development and Distribution License (the "License").
72633Sahl# You may not use this file except in compliance with the License.
82633Sahl#
92633Sahl# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
102633Sahl# or http://www.opensolaris.org/os/licensing.
112633Sahl# See the License for the specific language governing permissions
122633Sahl# and limitations under the License.
132633Sahl#
142633Sahl# When distributing Covered Code, include this CDDL HEADER in each
152633Sahl# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
162633Sahl# If applicable, add the following below this CDDL HEADER, with the
172633Sahl# fields enclosed by brackets "[]" replaced with your own identifying
182633Sahl# information: Portions Copyright [yyyy] [name of copyright owner]
192633Sahl#
202633Sahl# CDDL HEADER END
212633Sahl#
222633Sahl
232633Sahl#
246136Stomee# Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
252633Sahl# Use is subject to license terms.
262633Sahl#
272633Sahl
28*8287SJohn.Sonnenschein@Sun.COMrequire 5.8.4;
292633Sahl
302633Sahluse File::Find;
312633Sahluse File::Basename;
322633Sahluse Getopt::Std;
332633Sahluse Cwd;
342804Stomeeuse Cwd 'abs_path';
352633Sahl
362633Sahl$PNAME = $0;
372633Sahl$PNAME =~ s:.*/::;
386136Stomee$OPTSTR = 'abd:fghi:jlnqsx:';
396136Stomee$USAGE = "Usage: $PNAME [-abfghjlnqs] [-d dir] [-i isa] "
402633Sahl    . "[-x opt[=arg]] [file | dir ...]\n";
412633Sahl($MACH = `uname -p`) =~ s/\W*\n//;
426670Stariq($PLATFORM = `uname -i`) =~ s/\W*\n//;
432633Sahl
442633Sahl@dtrace_argv = ();
452633Sahl
462633Sahl$ksh_path = '/usr/bin/ksh';
472633Sahl
482633Sahl@files = ();
492804Stomee%exceptions = ();
506136Stomee%results = ();
512633Sahl$errs = 0;
522633Sahl
532633Sahl#
542633Sahl# If no test files are specified on the command-line, execute a find on "."
552633Sahl# and append any tst.*.d, tst.*.ksh, err.*.d or drp.*.d files found within
562633Sahl# the directory tree.
572633Sahl#
582633Sahlsub wanted
592633Sahl{
602633Sahl	push(@files, $File::Find::name)
612633Sahl	    if ($_ =~ /^(tst|err|drp)\..+\.(d|ksh)$/ && -f "$_");
622633Sahl}
632633Sahl
642633Sahlsub dirname {
652633Sahl	my($s) = @_;
662633Sahl	my($i);
672633Sahl
682633Sahl	$s = substr($s, 0, $i) if (($i = rindex($s, '/')) != -1);
692633Sahl	return $i == -1 ? '.' : $i == 0 ? '/' : $s;
702633Sahl}
712633Sahl
722633Sahlsub usage
732633Sahl{
742633Sahl	print $USAGE;
752633Sahl	print "\t -a  execute test suite using anonymous enablings\n";
762633Sahl	print "\t -b  execute bad ioctl test program\n";
772633Sahl	print "\t -d  specify directory for test results files and cores\n";
782633Sahl	print "\t -g  enable libumem debugging when running tests\n";
796136Stomee	print "\t -f  force bypassed tests to run\n";
802633Sahl	print "\t -h  display verbose usage message\n";
812633Sahl	print "\t -i  specify ISA to test instead of isaexec(3C) default\n";
826136Stomee	print "\t -j  execute test suite using jdtrace (Java API) only\n";
832633Sahl	print "\t -l  save log file of results and PIDs used by tests\n";
846136Stomee	print "\t -n  execute test suite using dtrace(1m) only\n";
852633Sahl	print "\t -q  set quiet mode (only report errors and summary)\n";
862633Sahl	print "\t -s  save results files even for tests that pass\n";
872633Sahl	print "\t -x  pass corresponding -x argument to dtrace(1M)\n";
882633Sahl	exit(2);
892633Sahl}
902633Sahl
912633Sahlsub errmsg
922633Sahl{
932633Sahl	my($msg) = @_;
942633Sahl
952633Sahl	print STDERR $msg;
962633Sahl	print LOG $msg if ($opt_l);
972633Sahl	$errs++;
982633Sahl}
992633Sahl
1002633Sahlsub fail
1012633Sahl{
1022633Sahl	my(@parms) = @_;
1032633Sahl	my($msg) = $parms[0];
1042633Sahl	my($errfile) = $parms[1];
1052633Sahl	my($n) = 0;
1062633Sahl	my($dest) = basename($file);
1072633Sahl
1082633Sahl	while (-d "$opt_d/failure.$n") {
1092633Sahl		$n++;
1102633Sahl	}
1112633Sahl
1122633Sahl	unless (mkdir "$opt_d/failure.$n") {
1132633Sahl		warn "ERROR: failed to make directory $opt_d/failure.$n: $!\n";
1142633Sahl		exit(125);
1152633Sahl	}
1162633Sahl
1172633Sahl	open(README, ">$opt_d/failure.$n/README");
1182633Sahl	print README "ERROR: " . $file . " " . $msg;
1192633Sahl
1202633Sahl	if (scalar @parms > 1) {
1212633Sahl		print README "; see $errfile\n";
1222633Sahl	} else {
1232633Sahl		if (-f "$opt_d/$pid.core") {
1242633Sahl			print README "; see $pid.core\n";
1252633Sahl		} else {
1262633Sahl			print README "\n";
1272633Sahl		}
1282633Sahl	}
1292633Sahl
1302633Sahl	close(README);
1312633Sahl
1322633Sahl	if (-f "$opt_d/$pid.out") {
1332633Sahl		rename("$opt_d/$pid.out", "$opt_d/failure.$n/$pid.out");
1342633Sahl		link("$file.out", "$opt_d/failure.$n/$dest.out");
1352633Sahl	}
1362633Sahl
1372633Sahl	if (-f "$opt_d/$pid.err") {
1382633Sahl		rename("$opt_d/$pid.err", "$opt_d/failure.$n/$pid.err");
1392633Sahl		link("$file.err", "$opt_d/failure.$n/$dest.err");
1402633Sahl	}
1412633Sahl
1422633Sahl	if (-f "$opt_d/$pid.core") {
1432633Sahl		rename("$opt_d/$pid.core", "$opt_d/failure.$n/$pid.core");
1442633Sahl	}
1452633Sahl
1462633Sahl	link("$file", "$opt_d/failure.$n/$dest");
1472633Sahl
1482633Sahl	$msg = "ERROR: " . $dest . " " . $msg;
1492633Sahl
1502633Sahl	if (scalar @parms > 1) {
1512633Sahl		$msg = $msg . "; see $errfile in failure.$n\n";
1522633Sahl	} else {
1532633Sahl		$msg = $msg . "; details in failure.$n\n";
1542633Sahl	}
1552633Sahl
1562633Sahl	errmsg($msg);
1572633Sahl}
1582633Sahl
1592633Sahlsub logmsg
1602633Sahl{
1612633Sahl	my($msg) = @_;
1622633Sahl
1632633Sahl	print STDOUT $msg unless ($opt_q);
1642633Sahl	print LOG $msg if ($opt_l);
1652633Sahl}
1662633Sahl
1672804Stomee# Trim leading and trailing whitespace
1682804Stomeesub trim {
1692804Stomee	my($s) = @_;
1702804Stomee
1712804Stomee	$s =~ s/^\s*//;
1722804Stomee	$s =~ s/\s*$//;
1732804Stomee	return $s;
1742804Stomee}
1752804Stomee
1766136Stomee# Load exception set of skipped tests from the file at the given
1776136Stomee# pathname. The test names are assumed to be paths relative to $dt_tst,
1786136Stomee# for example: common/aggs/tst.neglquant.d, and specify tests to be
1796136Stomee# skipped.
1802804Stomeesub load_exceptions {
1812804Stomee	my($listfile) = @_;
1822804Stomee	my($line) = "";
1832804Stomee
1846136Stomee	%exceptions = ();
1856136Stomee	if (length($listfile) > 0) {
1866136Stomee		exit(123) unless open(STDIN, "<$listfile");
1876136Stomee		while (<STDIN>) {
1886136Stomee			chomp;
1896136Stomee			$line = $_;
1906136Stomee			# line is non-empty and not a comment
1916136Stomee			if ((length($line) > 0) && ($line =~ /^\s*[^\s#]/ )) {
1926136Stomee				$exceptions{trim($line)} = 1;
1936136Stomee			}
1942804Stomee		}
1952804Stomee	}
1962804Stomee}
1972804Stomee
1986136Stomee# Return 1 if the test is found in the exception set, 0 otherwise.
1992804Stomeesub is_exception {
2002804Stomee	my($file) = @_;
2012804Stomee	my($i) = -1;
2022804Stomee
2036136Stomee	if (scalar(keys(%exceptions)) == 0) {
2046136Stomee		return 0;
2056136Stomee	}
2066136Stomee
2072804Stomee	# hash absolute pathname after $dt_tst/
2082804Stomee	$file = abs_path($file);
2092804Stomee	$i = index($file, $dt_tst);
2102804Stomee	if ($i == 0) {
2112804Stomee		$file = substr($file, length($dt_tst) + 1);
2122804Stomee		return $exceptions{$file};
2132804Stomee	}
2142804Stomee	return 0;
2152804Stomee}
2162804Stomee
2176136Stomee#
2186670Stariq# Iterate over the set of test files specified on the command-line or by a find
2196670Stariq# on "$defdir/common", "$defdir/$MACH" and "$defdir/$PLATFORM" and execute each
2206670Stariq# one.  If the test file is executable, we fork and exec it. If the test is a
2216670Stariq# .ksh file, we run it with $ksh_path. Otherwise we run dtrace -s on it.  If
2226670Stariq# the file is named tst.* we assume it should return exit status 0.  If the
2236670Stariq# file is named err.* we assume it should return exit status 1.  If the file is
2246670Stariq# named err.D_[A-Z0-9]+[.*].d we use dtrace -xerrtags and examine stderr to
2256670Stariq# ensure that a matching error tag was produced.  If the file is named
2266670Stariq# drp.[A-Z0-9]+[.*].d we use dtrace -xdroptags and examine stderr to ensure
2276670Stariq# that a matching drop tag was produced.  If any *.out or *.err files are found
2286670Stariq# we perform output comparisons.
2296136Stomee#
2306136Stomee# run_tests takes two arguments: The first is the pathname of the dtrace
2316136Stomee# command to invoke when running the tests. The second is the pathname
2326136Stomee# of a file (may be the empty string) listing tests that ought to be
2336136Stomee# skipped (skipped tests are listed as paths relative to $dt_tst, for
2346136Stomee# example: common/aggs/tst.neglquant.d).
2356136Stomee#
2366136Stomeesub run_tests {
2376136Stomee	my($dtrace, $exceptions_path) = @_;
2386136Stomee	my($passed) = 0;
2396136Stomee	my($bypassed) = 0;
2406136Stomee	my($failed) = $errs;
2416136Stomee	my($total) = 0;
2426136Stomee
2436136Stomee	die "$PNAME: $dtrace not found\n" unless (-x "$dtrace");
2446136Stomee	logmsg($dtrace . "\n");
2456136Stomee
2466136Stomee	load_exceptions($exceptions_path);
2476136Stomee
2486136Stomee	foreach $file (sort @files) {
2496136Stomee		$file =~ m:.*/((.*)\.(\w+)):;
2506136Stomee		$name = $1;
2516136Stomee		$base = $2;
2526136Stomee		$ext = $3;
2536136Stomee
2546136Stomee		$dir = dirname($file);
2556136Stomee		$isksh = 0;
2566136Stomee		$tag = 0;
2576136Stomee		$droptag = 0;
2586136Stomee
2596136Stomee		if ($name =~ /^tst\./) {
2606136Stomee			$isksh = ($ext eq 'ksh');
2616136Stomee			$status = 0;
2626136Stomee		} elsif ($name =~ /^err\.(D_[A-Z0-9_]+)\./) {
2636136Stomee			$status = 1;
2646136Stomee			$tag = $1;
2656136Stomee		} elsif ($name =~ /^err\./) {
2666136Stomee			$status = 1;
2676136Stomee		} elsif ($name =~ /^drp\.([A-Z0-9_]+)\./) {
2686136Stomee			$status = 0;
2696136Stomee			$droptag = $1;
2706136Stomee		} else {
2716136Stomee			errmsg("ERROR: $file is not a valid test file name\n");
2726136Stomee			next;
2736136Stomee		}
2746136Stomee
2756136Stomee		$fullname = "$dir/$name";
2766136Stomee		$exe = "$dir/$base.exe";
2776136Stomee		$exe_pid = -1;
2786136Stomee
2796136Stomee		if ($opt_a && ($status != 0 || $tag != 0 || $droptag != 0 ||
2806136Stomee		    -x $exe || $isksh || -x $fullname)) {
2816136Stomee			$bypassed++;
2826136Stomee			next;
2836136Stomee		}
2846136Stomee
2856136Stomee		if (!$opt_f && is_exception("$dir/$name")) {
2866136Stomee			$bypassed++;
2876136Stomee			next;
2886136Stomee		}
2896136Stomee
2906136Stomee		if (!$isksh && -x $exe) {
2916136Stomee			if (($exe_pid = fork()) == -1) {
2926136Stomee				errmsg(
2936136Stomee				    "ERROR: failed to fork to run $exe: $!\n");
2946136Stomee				next;
2956136Stomee			}
2966136Stomee
2976136Stomee			if ($exe_pid == 0) {
2986136Stomee				open(STDIN, '</dev/null');
2996136Stomee
3006136Stomee				exec($exe);
3016136Stomee
3026136Stomee				warn "ERROR: failed to exec $exe: $!\n";
3036136Stomee			}
3046136Stomee		}
3056136Stomee
3066136Stomee		logmsg("testing $file ... ");
3076136Stomee
3086136Stomee		if (($pid = fork()) == -1) {
3096136Stomee			errmsg("ERROR: failed to fork to run test $file: $!\n");
3106136Stomee			next;
3116136Stomee		}
3126136Stomee
3136136Stomee		if ($pid == 0) {
3146136Stomee			open(STDIN, '</dev/null');
3156136Stomee			exit(125) unless open(STDOUT, ">$opt_d/$$.out");
3166136Stomee			exit(125) unless open(STDERR, ">$opt_d/$$.err");
3176136Stomee
3186136Stomee			unless (chdir($dir)) {
3196136Stomee				warn "ERROR: failed to chdir for $file: $!\n";
3206136Stomee				exit(126);
3216136Stomee			}
3226136Stomee
3236136Stomee			push(@dtrace_argv, '-xerrtags') if ($tag);
3246136Stomee			push(@dtrace_argv, '-xdroptags') if ($droptag);
3256136Stomee			push(@dtrace_argv, $exe_pid) if ($exe_pid != -1);
3266136Stomee
3276136Stomee			if ($isksh) {
3286136Stomee				exit(123) unless open(STDIN, "<$name");
3296136Stomee				exec("$ksh_path /dev/stdin $dtrace");
3306136Stomee			} elsif (-x $name) {
3316136Stomee				warn "ERROR: $name is executable\n";
3326136Stomee				exit(1);
3336136Stomee			} else {
3346136Stomee				if ($tag == 0 && $status == $0 && $opt_a) {
3356136Stomee					push(@dtrace_argv, '-A');
3366136Stomee				}
3376136Stomee
3386136Stomee				push(@dtrace_argv, '-C');
3396136Stomee				push(@dtrace_argv, '-s');
3406136Stomee				push(@dtrace_argv, $name);
3416136Stomee				exec($dtrace, @dtrace_argv);
3426136Stomee			}
3436136Stomee
3446136Stomee			warn "ERROR: failed to exec for $file: $!\n";
3456136Stomee			exit(127);
3466136Stomee		}
3476136Stomee
3486136Stomee		if (waitpid($pid, 0) == -1) {
3496136Stomee			errmsg("ERROR: timed out waiting for $file\n");
3506136Stomee			kill(9, $exe_pid) if ($exe_pid != -1);
3516136Stomee			kill(9, $pid);
3526136Stomee			next;
3536136Stomee		}
3546136Stomee
3556136Stomee		kill(9, $exe_pid) if ($exe_pid != -1);
3566136Stomee
3576136Stomee		if ($tag == 0 && $status == $0 && $opt_a) {
3586136Stomee			#
3596136Stomee			# We can chuck the earler output.
3606136Stomee			#
3616136Stomee			unlink($pid . '.out');
3626136Stomee			unlink($pid . '.err');
3636136Stomee
3646136Stomee			#
3656136Stomee			# This is an anonymous enabling.  We need to get
3666136Stomee			# the module unloaded.
3676136Stomee			#
3686136Stomee			system("dtrace -ae 1> /dev/null 2> /dev/null");
3696136Stomee			system("svcadm disable -s " .
3706136Stomee			    "svc:/network/nfs/mapid:default");
3716136Stomee			system("modunload -i 0 ; modunload -i 0 ; " .
3726136Stomee			    "modunload -i 0");
3736136Stomee			if (!system("modinfo | grep dtrace")) {
3746136Stomee				warn "ERROR: couldn't unload dtrace\n";
3756136Stomee				system("svcadm enable " .
3766136Stomee				    "-s svc:/network/nfs/mapid:default");
3776136Stomee				exit(124);
3786136Stomee			}
3796136Stomee
3806136Stomee			#
3816136Stomee			# DTrace is gone.  Now update_drv(1M), and rip
3826136Stomee			# everything out again.
3836136Stomee			#
3846136Stomee			system("update_drv dtrace");
3856136Stomee			system("dtrace -ae 1> /dev/null 2> /dev/null");
3866136Stomee			system("modunload -i 0 ; modunload -i 0 ; " .
3876136Stomee			    "modunload -i 0");
3886136Stomee			if (!system("modinfo | grep dtrace")) {
3896136Stomee				warn "ERROR: couldn't unload dtrace\n";
3906136Stomee				system("svcadm enable " .
3916136Stomee				    "-s svc:/network/nfs/mapid:default");
3926136Stomee				exit(124);
3936136Stomee			}
3946136Stomee
3956136Stomee			#
3966136Stomee			# Now bring DTrace back in.
3976136Stomee			#
3986136Stomee			system("sync ; sync");
3996136Stomee			system("dtrace -l -n bogusprobe 1> /dev/null " .
4006136Stomee			    "2> /dev/null");
4016136Stomee			system("svcadm enable -s " .
4026136Stomee			    "svc:/network/nfs/mapid:default");
4036136Stomee
4046136Stomee			#
4056136Stomee			# That should have caused DTrace to reload with
4066136Stomee			# the new configuration file.  Now we can try to
4076136Stomee			# snag our anonymous state.
4086136Stomee			#
4096136Stomee			if (($pid = fork()) == -1) {
4106136Stomee				errmsg("ERROR: failed to fork to run " .
4116136Stomee				    "test $file: $!\n");
4126136Stomee				next;
4136136Stomee			}
4146136Stomee
4156136Stomee			if ($pid == 0) {
4166136Stomee				open(STDIN, '</dev/null');
4176136Stomee				exit(125) unless open(STDOUT, ">$opt_d/$$.out");
4186136Stomee				exit(125) unless open(STDERR, ">$opt_d/$$.err");
4196136Stomee
4206136Stomee				push(@dtrace_argv, '-a');
4216136Stomee
4226136Stomee				unless (chdir($dir)) {
4236136Stomee					warn "ERROR: failed to chdir " .
4246136Stomee					    "for $file: $!\n";
4256136Stomee					exit(126);
4266136Stomee				}
4276136Stomee
4286136Stomee				exec($dtrace, @dtrace_argv);
4296136Stomee				warn "ERROR: failed to exec for $file: $!\n";
4306136Stomee				exit(127);
4316136Stomee			}
4326136Stomee
4336136Stomee			if (waitpid($pid, 0) == -1) {
4346136Stomee				errmsg("ERROR: timed out waiting for $file\n");
4356136Stomee				kill(9, $pid);
4366136Stomee				next;
4376136Stomee			}
4386136Stomee		}
4396136Stomee
4406136Stomee		logmsg("[$pid]\n");
4416136Stomee		$wstat = $?;
4426136Stomee		$wifexited = ($wstat & 0xFF) == 0;
4436136Stomee		$wexitstat = ($wstat >> 8) & 0xFF;
4446136Stomee		$wtermsig = ($wstat & 0x7F);
4456136Stomee
4466136Stomee		if (!$wifexited) {
4476136Stomee			fail("died from signal $wtermsig");
4486136Stomee			next;
4496136Stomee		}
4506136Stomee
4516136Stomee		if ($wexitstat == 125) {
4526136Stomee			die "$PNAME: failed to create output file in $opt_d " .
4536136Stomee			    "(cd elsewhere or use -d)\n";
4546136Stomee		}
4556136Stomee
4566136Stomee		if ($wexitstat != $status) {
4576136Stomee			fail("returned $wexitstat instead of $status");
4586136Stomee			next;
4596136Stomee		}
4606136Stomee
4616136Stomee		if (-f "$file.out" &&
4626136Stomee		    system("cmp -s $file.out $opt_d/$pid.out") != 0) {
4636136Stomee			fail("stdout mismatch", "$pid.out");
4646136Stomee			next;
4656136Stomee		}
4666136Stomee
4676136Stomee		if (-f "$file.err" &&
4686136Stomee		    system("cmp -s $file.err $opt_d/$pid.err") != 0) {
4696136Stomee			fail("stderr mismatch: see $pid.err");
4706136Stomee			next;
4716136Stomee		}
4726136Stomee
4736136Stomee		if ($tag) {
4746136Stomee			open(TSTERR, "<$opt_d/$pid.err");
4756136Stomee			$tsterr = <TSTERR>;
4766136Stomee			close(TSTERR);
4776136Stomee
4786136Stomee			unless ($tsterr =~ /: \[$tag\] line \d+:/) {
4796136Stomee				fail("errtag mismatch: see $pid.err");
4806136Stomee				next;
4816136Stomee			}
4826136Stomee		}
4836136Stomee
4846136Stomee		if ($droptag) {
4856136Stomee			$found = 0;
4866136Stomee			open(TSTERR, "<$opt_d/$pid.err");
4876136Stomee
4886136Stomee			while (<TSTERR>) {
4896136Stomee				if (/\[$droptag\] /) {
4906136Stomee					$found = 1;
4916136Stomee					last;
4926136Stomee				}
4936136Stomee			}
4946136Stomee
4956136Stomee			close (TSTERR);
4966136Stomee
4976136Stomee			unless ($found) {
4986136Stomee				fail("droptag mismatch: see $pid.err");
4996136Stomee				next;
5006136Stomee			}
5016136Stomee		}
5026136Stomee
5036136Stomee		unless ($opt_s) {
5046136Stomee			unlink($pid . '.out');
5056136Stomee			unlink($pid . '.err');
5066136Stomee		}
5076136Stomee	}
5086136Stomee
5096136Stomee	if ($opt_a) {
5106136Stomee		#
5116136Stomee		# If we're running with anonymous enablings, we need to
5126136Stomee		# restore the .conf file.
5136136Stomee		#
5146136Stomee		system("dtrace -A 1> /dev/null 2> /dev/null");
5156136Stomee		system("dtrace -ae 1> /dev/null 2> /dev/null");
5166136Stomee		system("modunload -i 0 ; modunload -i 0 ; modunload -i 0");
5176136Stomee		system("update_drv dtrace");
5186136Stomee	}
5196136Stomee
5206136Stomee	$total = scalar(@files);
5216136Stomee	$failed = $errs - $failed;
5226136Stomee	$passed = ($total - $failed - $bypassed);
5236136Stomee	$results{$dtrace} = {
5246136Stomee		"passed" => $passed,
5256136Stomee		"bypassed" => $bypassed,
5266136Stomee		"failed" => $failed,
5276136Stomee		"total" => $total
5286136Stomee	};
5296136Stomee}
5306136Stomee
5312804Stomeedie $USAGE unless (getopts($OPTSTR));
5322633Sahlusage() if ($opt_h);
5332633Sahl
5342633Sahlforeach $arg (@ARGV) {
5352633Sahl	if (-f $arg) {
5362633Sahl		push(@files, $arg);
5372633Sahl	} elsif (-d $arg) {
5382633Sahl		find(\&wanted, $arg);
5392633Sahl	} else {
5402633Sahl		die "$PNAME: $arg is not a valid file or directory\n";
5412633Sahl	}
5422633Sahl}
5432633Sahl
5442804Stomee$dt_tst = '/opt/SUNWdtrt/tst';
5452804Stomee$dt_bin = '/opt/SUNWdtrt/bin';
5462804Stomee$defdir = -d $dt_tst ? $dt_tst : '.';
5472804Stomee$bindir = -d $dt_bin ? $dt_bin : '.';
5482633Sahl
5492633Sahlfind(\&wanted, "$defdir/common") if (scalar(@ARGV) == 0);
5502633Sahlfind(\&wanted, "$defdir/$MACH") if (scalar(@ARGV) == 0);
5516670Stariqfind(\&wanted, "$defdir/$PLATFORM") if (scalar(@ARGV) == 0);
5522633Sahldie $USAGE if (scalar(@files) == 0);
5532633Sahl
5546136Stomee$dtrace_path = '/usr/sbin/dtrace';
5556136Stomee$jdtrace_path = "$bindir/jdtrace";
5566136Stomee
5576136Stomee%exception_lists = ("$jdtrace_path" => "$bindir/exception.lst");
5586136Stomee
5596136Stomeeif ($opt_j || $opt_n || $opt_i) {
5606136Stomee	@dtrace_cmds = ();
5616136Stomee	push(@dtrace_cmds, $dtrace_path) if ($opt_n);
5626136Stomee	push(@dtrace_cmds, $jdtrace_path) if ($opt_j);
5636136Stomee	push(@dtrace_cmds, "/usr/sbin/$opt_i/dtrace") if ($opt_i);
5646136Stomee} else {
5656136Stomee	@dtrace_cmds = ($dtrace_path, $jdtrace_path);
5666136Stomee}
5676136Stomee
5682633Sahlif ($opt_d) {
5692633Sahl	die "$PNAME: -d arg must be absolute path\n" unless ($opt_d =~ /^\//);
5702633Sahl	die "$PNAME: -d arg $opt_d is not a directory\n" unless (-d "$opt_d");
5712633Sahl	system("coreadm -p $opt_d/%p.core");
5722633Sahl} else {
5732633Sahl	my $dir = getcwd;
5742633Sahl	system("coreadm -p $dir/%p.core");
5752633Sahl	$opt_d = '.';
5762633Sahl}
5772633Sahl
5782633Sahlif ($opt_x) {
5792633Sahl	push(@dtrace_argv, '-x');
5802633Sahl	push(@dtrace_argv, $opt_x);
5812633Sahl}
5822633Sahl
5832633Sahldie "$PNAME: failed to open $PNAME.$$.log: $!\n"
5842633Sahl    unless (!$opt_l || open(LOG, ">$PNAME.$$.log"));
5852633Sahl
5862633Sahlif ($opt_g) {
5872633Sahl	$ENV{'UMEM_DEBUG'} = 'default,verbose';
5882633Sahl	$ENV{'UMEM_LOGGING'} = 'fail,contents';
5892633Sahl	$ENV{'LD_PRELOAD'} = 'libumem.so';
5902633Sahl}
5912633Sahl
5922633Sahl#
5932633Sahl# Ensure that $PATH contains a cc(1) so that we can execute the
5942633Sahl# test programs that require compilation of C code.
5952633Sahl#
5962769Sahl$ENV{'PATH'} = $ENV{'PATH'} . ':/ws/onnv-tools/SUNWspro/SS11/bin';
5972633Sahl
5982633Sahlif ($opt_b) {
5992633Sahl	logmsg("badioctl'ing ... ");
6002633Sahl
6012633Sahl	if (($badioctl = fork()) == -1) {
6022633Sahl		errmsg("ERROR: failed to fork to run badioctl: $!\n");
6032633Sahl		next;
6042633Sahl	}
6052633Sahl
6062633Sahl	if ($badioctl == 0) {
6072633Sahl		open(STDIN, '</dev/null');
6082633Sahl		exit(125) unless open(STDOUT, ">$opt_d/$$.out");
6092633Sahl		exit(125) unless open(STDERR, ">$opt_d/$$.err");
6102633Sahl
6112633Sahl		exec($bindir . "/badioctl");
6122633Sahl		warn "ERROR: failed to exec badioctl: $!\n";
6132633Sahl		exit(127);
6142633Sahl	}
6152633Sahl
6162633Sahl
6172633Sahl	logmsg("[$badioctl]\n");
6182633Sahl
6192633Sahl	#
6202633Sahl	# If we're going to be bad, we're just going to iterate over each
6212633Sahl	# test file.
6222633Sahl	#
6232633Sahl	foreach $file (sort @files) {
6242633Sahl		($name = $file) =~ s:.*/::;
6252633Sahl		$dir = dirname($file);
6262633Sahl
6272633Sahl		if (!($name =~ /^tst\./ && $name =~ /\.d$/)) {
6282633Sahl			next;
6292633Sahl		}
6302633Sahl
6312633Sahl		logmsg("baddof'ing $file ... ");
6322633Sahl
6332633Sahl		if (($pid = fork()) == -1) {
6342633Sahl			errmsg("ERROR: failed to fork to run baddof: $!\n");
6352633Sahl			next;
6362633Sahl		}
6372633Sahl
6382633Sahl		if ($pid == 0) {
6392633Sahl			open(STDIN, '</dev/null');
6402633Sahl			exit(125) unless open(STDOUT, ">$opt_d/$$.out");
6412633Sahl			exit(125) unless open(STDERR, ">$opt_d/$$.err");
6422633Sahl
6432633Sahl			unless (chdir($dir)) {
6442633Sahl				warn "ERROR: failed to chdir for $file: $!\n";
6452633Sahl				exit(126);
6462633Sahl			}
6472633Sahl
6482633Sahl			exec($bindir . "/baddof", $name);
6492633Sahl
6502633Sahl			warn "ERROR: failed to exec for $file: $!\n";
6512633Sahl			exit(127);
6522633Sahl		}
6532633Sahl
6542633Sahl		sleep 60;
6552633Sahl		kill(9, $pid);
6562633Sahl		waitpid($pid, 0);
6572633Sahl
6582633Sahl		logmsg("[$pid]\n");
6592633Sahl
6602633Sahl		unless ($opt_s) {
6612633Sahl			unlink($pid . '.out');
6622633Sahl			unlink($pid . '.err');
6632633Sahl		}
6642633Sahl	}
6652633Sahl
6662633Sahl	kill(9, $badioctl);
6672633Sahl	waitpid($badioctl, 0);
6682633Sahl
6692633Sahl	unless ($opt_s) {
6702633Sahl		unlink($badioctl . '.out');
6712633Sahl		unlink($badioctl . '.err');
6722633Sahl	}
6732633Sahl
6742633Sahl	exit(0);
6752633Sahl}
6762633Sahl
6772633Sahl#
6786136Stomee# Run all the tests specified on the command-line (the entire test suite
6796136Stomee# by default) once for each dtrace command tested, skipping any tests
6806136Stomee# not valid for that command.
6816136Stomee#
6826136Stomeeforeach $dtrace_cmd (@dtrace_cmds) {
6836136Stomee	run_tests($dtrace_cmd, $exception_lists{$dtrace_cmd});
6842633Sahl}
6852633Sahl
6862633Sahl$opt_q = 0; # force final summary to appear regardless of -q option
6872633Sahl
6882633Sahllogmsg("\n==== TEST RESULTS ====\n");
6896136Stomeeforeach $key (keys %results) {
6906136Stomee	my $passed = $results{$key}{"passed"};
6916136Stomee	my $bypassed = $results{$key}{"bypassed"};
6926136Stomee	my $failed = $results{$key}{"failed"};
6936136Stomee	my $total = $results{$key}{"total"};
6942633Sahl
6956136Stomee	logmsg("\n     mode: " . $key . "\n");
6966136Stomee	logmsg("   passed: " . $passed . "\n");
6976136Stomee	if ($bypassed) {
6986136Stomee		logmsg(" bypassed: " . $bypassed . "\n");
6996136Stomee	}
7006136Stomee	logmsg("   failed: " . $failed . "\n");
7016136Stomee	logmsg("    total: " . $total . "\n");
7022633Sahl}
7032633Sahl
7042633Sahlexit($errs != 0);
705