dtest.pl revision 9512fe850e98fdd448c638ca63fdd92a8a510255
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
#
# Copyright 2006 Sun Microsystems, Inc. All rights reserved.
# Use is subject to license terms.
#
#ident "%Z%%M% %I% %E% SMI"
require 5.6.1;
use Cwd;
$PNAME = $0;
$PNAME =~ s:.*/::;
$USAGE = "Usage: $PNAME [-abghlqsu] [-d dir] [-i isa] "
. "[-x opt[=arg]] [file | dir ...]\n";
$dtrace_path = '/usr/sbin/dtrace';
@dtrace_argv = ();
@files = ();
$errs = 0;
$bypassed = 0;
#
# If no test files are specified on the command-line, execute a find on "."
# and append any tst.*.d, tst.*.ksh, err.*.d or drp.*.d files found within
# the directory tree.
#
sub wanted
{
}
sub dirname {
my($s) = @_;
my($i);
$s = substr($s, 0, $i) if (($i = rindex($s, '/')) != -1);
return $i == -1 ? '.' : $i == 0 ? '/' : $s;
}
sub usage
{
print $USAGE;
print "\t -a execute test suite using anonymous enablings\n";
print "\t -b execute bad ioctl test program\n";
print "\t -d specify directory for test results files and cores\n";
print "\t -g enable libumem debugging when running tests\n";
print "\t -h display verbose usage message\n";
print "\t -i specify ISA to test instead of isaexec(3C) default\n";
print "\t -l save log file of results and PIDs used by tests\n";
print "\t -q set quiet mode (only report errors and summary)\n";
print "\t -s save results files even for tests that pass\n";
print "\t -x pass corresponding -x argument to dtrace(1M)\n";
exit(2);
}
sub errmsg
{
my($msg) = @_;
$errs++;
}
sub fail
{
my(@parms) = @_;
my($n) = 0;
$n++;
}
exit(125);
}
if (scalar @parms > 1) {
print README "; see $errfile\n";
} else {
if (-f "$opt_d/$pid.core") {
print README "; see $pid.core\n";
} else {
print README "\n";
}
}
close(README);
if (-f "$opt_d/$pid.out") {
}
if (-f "$opt_d/$pid.err") {
}
if (-f "$opt_d/$pid.core") {
}
if (scalar @parms > 1) {
} else {
}
}
sub logmsg
{
my($msg) = @_;
}
if (-f $arg) {
} elsif (-d $arg) {
} else {
die "$PNAME: $arg is not a valid file or directory\n";
}
}
if ($opt_d) {
die "$PNAME: -d arg must be absolute path\n" unless ($opt_d =~ /^\//);
die "$PNAME: -d arg $opt_d is not a directory\n" unless (-d "$opt_d");
system("coreadm -p $opt_d/%p.core");
} else {
system("coreadm -p $dir/%p.core");
$opt_d = '.';
}
if ($opt_i) {
$dtrace_path = "/usr/sbin/$opt_i/dtrace";
die "$PNAME: dtrace(1M) for ISA $opt_i not found\n"
unless (-x "$dtrace_path");
}
if ($opt_x) {
push(@dtrace_argv, '-x');
push(@dtrace_argv, $opt_x);
}
die "$PNAME: failed to open $PNAME.$$.log: $!\n"
if ($opt_g) {
}
#
# Ensure that $PATH contains a cc(1) so that we can execute the
# test programs that require compilation of C code.
#
if ($opt_b) {
logmsg("badioctl'ing ... ");
if (($badioctl = fork()) == -1) {
errmsg("ERROR: failed to fork to run badioctl: $!\n");
next;
}
if ($badioctl == 0) {
exec($bindir . "/badioctl");
warn "ERROR: failed to exec badioctl: $!\n";
exit(127);
}
logmsg("[$badioctl]\n");
#
# If we're going to be bad, we're just going to iterate over each
# test file.
#
next;
}
logmsg("baddof'ing $file ... ");
if (($pid = fork()) == -1) {
errmsg("ERROR: failed to fork to run baddof: $!\n");
next;
}
if ($pid == 0) {
unless (chdir($dir)) {
warn "ERROR: failed to chdir for $file: $!\n";
exit(126);
}
warn "ERROR: failed to exec for $file: $!\n";
exit(127);
}
sleep 60;
kill(9, $pid);
waitpid($pid, 0);
logmsg("[$pid]\n");
unless ($opt_s) {
unlink($pid . '.out');
unlink($pid . '.err');
}
}
kill(9, $badioctl);
waitpid($badioctl, 0);
unless ($opt_s) {
unlink($badioctl . '.out');
unlink($badioctl . '.err');
}
exit(0);
}
if ($opt_u) {
logmsg "spawning module unloading process... ";
$unloader = fork;
#
# Couldn't fork for some reason.
#
die "couldn't fork: $!\n";
}
if ($unloader == 0) {
#
# We're in the child. Go modunload krazy.
#
for (;;) {
system("modunload -i 0");
}
} else {
logmsg "[$unloader]\n";
kill 9, $unloader;
exit($errs != 0);
};
}
}
#
# Iterate over the set of test files specified on the command-line or located
# by a find on "." and execute each one. If the test file is executable, we
# assume it is a #! script and run it. Otherwise we run dtrace -s on it.
# If the file is named tst.* we assume it should return exit status 0.
# If the file is named err.* we assume it should return exit status 1.
# If the file is named err.D_[A-Z0-9]+[.*].d we use dtrace -xerrtags and
# examine stderr to ensure that a matching error tag was produced.
# If the file is named drp.[A-Z0-9]+[.*].d we use dtrace -xdroptags and
# examine stderr to ensure that a matching drop tag was produced.
# If any *.out or *.err files are found we perform output comparisons.
#
$file =~ m:.*/((.*)\.(\w+)):;
$name = $1;
$base = $2;
$ext = $3;
$isksh = 0;
$tag = 0;
$droptag = 0;
$status = 0;
$status = 1;
$tag = $1;
} elsif ($name =~ /^err\./) {
$status = 1;
$status = 0;
$droptag = $1;
} else {
errmsg("ERROR: $file is not a valid test file name\n");
next;
}
$fullname = "$dir/$name";
$exe = "$dir/$base.exe";
$exe_pid = -1;
$bypassed++;
next;
}
if (($exe_pid = fork()) == -1) {
errmsg("ERROR: failed to fork to run $exe: $!\n");
next;
}
if ($exe_pid == 0) {
exec($exe);
warn "ERROR: failed to exec $exe: $!\n";
}
}
logmsg("testing $file ... ");
if (($pid = fork()) == -1) {
errmsg("ERROR: failed to fork to run test $file: $!\n");
next;
}
if ($pid == 0) {
unless (chdir($dir)) {
warn "ERROR: failed to chdir for $file: $!\n";
exit(126);
}
if ($isksh) {
exec($ksh_path);
} elsif (-x $name) {
warn "ERROR: $name is executable\n";
exit(1);
} else {
push(@dtrace_argv, '-A');
}
push(@dtrace_argv, '-C');
push(@dtrace_argv, '-s');
push(@dtrace_argv, $name);
exec($dtrace_path, @dtrace_argv);
}
warn "ERROR: failed to exec for $file: $!\n";
exit(127);
}
errmsg("ERROR: timed out waiting for $file\n");
kill(9, $pid);
next;
}
#
# We can chuck the earler output.
#
unlink($pid . '.out');
unlink($pid . '.err');
#
# This is an anonymous enabling. We need to get the module
# unloaded.
#
system("modunload -i 0 ; modunload -i 0 ; modunload -i 0");
if (!system("modinfo | grep dtrace")) {
warn "ERROR: couldn't unload dtrace\n";
system("svcadm enable " .
exit(124);
}
#
# DTrace is gone. Now update_drv(1M), and rip everything out
# again.
#
system("update_drv dtrace");
system("modunload -i 0 ; modunload -i 0 ; modunload -i 0");
if (!system("modinfo | grep dtrace")) {
warn "ERROR: couldn't unload dtrace\n";
system("svcadm enable " .
exit(124);
}
#
# Now bring DTrace back in.
#
system("sync ; sync");
#
# That should have caused DTrace to reload with the new
# configuration file. Now we can try to snag our anonymous
# state.
#
if (($pid = fork()) == -1) {
errmsg("ERROR: failed to fork to run test $file: $!\n");
next;
}
if ($pid == 0) {
push(@dtrace_argv, '-a');
unless (chdir($dir)) {
warn "ERROR: failed to chdir for $file: $!\n";
exit(126);
}
exec($dtrace_path, @dtrace_argv);
warn "ERROR: failed to exec for $file: $!\n";
exit(127);
}
errmsg("ERROR: timed out waiting for $file\n");
kill(9, $pid);
next;
}
}
logmsg("[$pid]\n");
$wstat = $?;
if (!$wifexited) {
fail("died from signal $wtermsig");
next;
}
if ($wexitstat == 125) {
die "$PNAME: failed to create output file in $opt_d " .
"(cd elsewhere or use -d)\n";
}
fail("returned $wexitstat instead of $status");
next;
}
if (-f "$file.out" && system("cmp -s $file.out $opt_d/$pid.out") != 0) {
next;
}
if (-f "$file.err" && system("cmp -s $file.err $opt_d/$pid.err") != 0) {
fail("stderr mismatch: see $pid.err");
next;
}
if ($tag) {
open(TSTERR, "<$opt_d/$pid.err");
close(TSTERR);
fail("errtag mismatch: see $pid.err");
next;
}
}
if ($droptag) {
$found = 0;
open(TSTERR, "<$opt_d/$pid.err");
while (<TSTERR>) {
if (/\[$droptag\] /) {
$found = 1;
last;
}
}
close (TSTERR);
unless ($found) {
fail("droptag mismatch: see $pid.err");
next;
}
}
unless ($opt_s) {
unlink($pid . '.out');
unlink($pid . '.err');
}
}
if ($opt_a) {
#
# If we're running with anonymous enablings, we need to restore the
# .conf file.
#
system("modunload -i 0 ; modunload -i 0 ; modunload -i 0");
system("update_drv dtrace");
}
logmsg("\n==== TEST RESULTS ====\n");
if ($bypassed) {
}
if ($opt_u) {
kill 9, $unloader;
waitpid $unloader, 0;
}
exit($errs != 0);