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# 24e77b06d2Stomee# Copyright 2008 Sun Microsystems, Inc. All rights reserved. 259512fe85Sahl# Use is subject to license terms. 269512fe85Sahl# 279512fe85Sahl 28c090e5dfSBryan Cantrill# 29c090e5dfSBryan Cantrill# Copyright (c) 2011, Joyent, Inc. All rights reserved. 30*e5803b76SAdam H. Leventhal# Copyright (c) 2012 by Delphix. All rights reserved. 31c090e5dfSBryan Cantrill# 32df0345f7SJohn Sonnenscheinrequire 5.8.4; 339512fe85Sahl 349512fe85Sahluse File::Find; 359512fe85Sahluse File::Basename; 369512fe85Sahluse Getopt::Std; 379512fe85Sahluse Cwd; 3823b5c241Stomeeuse Cwd 'abs_path'; 399512fe85Sahl 409512fe85Sahl$PNAME = $0; 419512fe85Sahl$PNAME =~ s:.*/::; 42c090e5dfSBryan Cantrill$OPTSTR = 'abd:fFghi:jlnqsx:'; 43c090e5dfSBryan Cantrill$USAGE = "Usage: $PNAME [-abfFghjlnqs] [-d dir] [-i isa] " 449512fe85Sahl . "[-x opt[=arg]] [file | dir ...]\n"; 459512fe85Sahl($MACH = `uname -p`) =~ s/\W*\n//; 46c7158ae9Stariq($PLATFORM = `uname -i`) =~ s/\W*\n//; 479512fe85Sahl 489512fe85Sahl@dtrace_argv = (); 499512fe85Sahl 509512fe85Sahl$ksh_path = '/usr/bin/ksh'; 519512fe85Sahl 529512fe85Sahl@files = (); 5323b5c241Stomee%exceptions = (); 54e77b06d2Stomee%results = (); 559512fe85Sahl$errs = 0; 569512fe85Sahl 579512fe85Sahl# 589512fe85Sahl# If no test files are specified on the command-line, execute a find on "." 599512fe85Sahl# and append any tst.*.d, tst.*.ksh, err.*.d or drp.*.d files found within 609512fe85Sahl# the directory tree. 619512fe85Sahl# 629512fe85Sahlsub wanted 639512fe85Sahl{ 649512fe85Sahl push(@files, $File::Find::name) 659512fe85Sahl if ($_ =~ /^(tst|err|drp)\..+\.(d|ksh)$/ && -f "$_"); 669512fe85Sahl} 679512fe85Sahl 689512fe85Sahlsub dirname { 699512fe85Sahl my($s) = @_; 709512fe85Sahl my($i); 719512fe85Sahl 729512fe85Sahl $s = substr($s, 0, $i) if (($i = rindex($s, '/')) != -1); 739512fe85Sahl return $i == -1 ? '.' : $i == 0 ? '/' : $s; 749512fe85Sahl} 759512fe85Sahl 76c090e5dfSBryan Cantrillsub inpath 77c090e5dfSBryan Cantrill{ 78c090e5dfSBryan Cantrill my ($exec) = (@_); 79c090e5dfSBryan Cantrill my @path = File::Spec->path(); 80c090e5dfSBryan Cantrill 81c090e5dfSBryan Cantrill for my $dir (@path) { 82c090e5dfSBryan Cantrill if (-x $dir . "/" . $exec) { 83c090e5dfSBryan Cantrill return 1; 84c090e5dfSBryan Cantrill } 85c090e5dfSBryan Cantrill } 86c090e5dfSBryan Cantrill 87c090e5dfSBryan Cantrill return 0; 88c090e5dfSBryan Cantrill} 89c090e5dfSBryan Cantrill 909512fe85Sahlsub usage 919512fe85Sahl{ 929512fe85Sahl print $USAGE; 939512fe85Sahl print "\t -a execute test suite using anonymous enablings\n"; 949512fe85Sahl print "\t -b execute bad ioctl test program\n"; 959512fe85Sahl print "\t -d specify directory for test results files and cores\n"; 969512fe85Sahl print "\t -g enable libumem debugging when running tests\n"; 97e77b06d2Stomee print "\t -f force bypassed tests to run\n"; 98c090e5dfSBryan Cantrill print "\t -F force tests to be run, even if missing dependencies\n"; 999512fe85Sahl print "\t -h display verbose usage message\n"; 1009512fe85Sahl print "\t -i specify ISA to test instead of isaexec(3C) default\n"; 101e77b06d2Stomee print "\t -j execute test suite using jdtrace (Java API) only\n"; 1029512fe85Sahl print "\t -l save log file of results and PIDs used by tests\n"; 103e77b06d2Stomee print "\t -n execute test suite using dtrace(1m) only\n"; 1049512fe85Sahl print "\t -q set quiet mode (only report errors and summary)\n"; 1059512fe85Sahl print "\t -s save results files even for tests that pass\n"; 1069512fe85Sahl print "\t -x pass corresponding -x argument to dtrace(1M)\n"; 1079512fe85Sahl exit(2); 1089512fe85Sahl} 1099512fe85Sahl 1109512fe85Sahlsub errmsg 1119512fe85Sahl{ 1129512fe85Sahl my($msg) = @_; 1139512fe85Sahl 1149512fe85Sahl print STDERR $msg; 1159512fe85Sahl print LOG $msg if ($opt_l); 1169512fe85Sahl $errs++; 1179512fe85Sahl} 1189512fe85Sahl 1199512fe85Sahlsub fail 1209512fe85Sahl{ 1219512fe85Sahl my(@parms) = @_; 1229512fe85Sahl my($msg) = $parms[0]; 1239512fe85Sahl my($errfile) = $parms[1]; 1249512fe85Sahl my($n) = 0; 1259512fe85Sahl my($dest) = basename($file); 1269512fe85Sahl 1279512fe85Sahl while (-d "$opt_d/failure.$n") { 1289512fe85Sahl $n++; 1299512fe85Sahl } 1309512fe85Sahl 1319512fe85Sahl unless (mkdir "$opt_d/failure.$n") { 1329512fe85Sahl warn "ERROR: failed to make directory $opt_d/failure.$n: $!\n"; 1339512fe85Sahl exit(125); 1349512fe85Sahl } 1359512fe85Sahl 1369512fe85Sahl open(README, ">$opt_d/failure.$n/README"); 1379512fe85Sahl print README "ERROR: " . $file . " " . $msg; 1389512fe85Sahl 1399512fe85Sahl if (scalar @parms > 1) { 1409512fe85Sahl print README "; see $errfile\n"; 1419512fe85Sahl } else { 1429512fe85Sahl if (-f "$opt_d/$pid.core") { 1439512fe85Sahl print README "; see $pid.core\n"; 1449512fe85Sahl } else { 1459512fe85Sahl print README "\n"; 1469512fe85Sahl } 1479512fe85Sahl } 1489512fe85Sahl 1499512fe85Sahl close(README); 1509512fe85Sahl 1519512fe85Sahl if (-f "$opt_d/$pid.out") { 1529512fe85Sahl rename("$opt_d/$pid.out", "$opt_d/failure.$n/$pid.out"); 1539512fe85Sahl link("$file.out", "$opt_d/failure.$n/$dest.out"); 1549512fe85Sahl } 1559512fe85Sahl 1569512fe85Sahl if (-f "$opt_d/$pid.err") { 1579512fe85Sahl rename("$opt_d/$pid.err", "$opt_d/failure.$n/$pid.err"); 1589512fe85Sahl link("$file.err", "$opt_d/failure.$n/$dest.err"); 1599512fe85Sahl } 1609512fe85Sahl 1619512fe85Sahl if (-f "$opt_d/$pid.core") { 1629512fe85Sahl rename("$opt_d/$pid.core", "$opt_d/failure.$n/$pid.core"); 1639512fe85Sahl } 1649512fe85Sahl 1659512fe85Sahl link("$file", "$opt_d/failure.$n/$dest"); 1669512fe85Sahl 1679512fe85Sahl $msg = "ERROR: " . $dest . " " . $msg; 1689512fe85Sahl 1699512fe85Sahl if (scalar @parms > 1) { 1709512fe85Sahl $msg = $msg . "; see $errfile in failure.$n\n"; 1719512fe85Sahl } else { 1729512fe85Sahl $msg = $msg . "; details in failure.$n\n"; 1739512fe85Sahl } 1749512fe85Sahl 1759512fe85Sahl errmsg($msg); 1769512fe85Sahl} 1779512fe85Sahl 1789512fe85Sahlsub logmsg 1799512fe85Sahl{ 1809512fe85Sahl my($msg) = @_; 1819512fe85Sahl 1829512fe85Sahl print STDOUT $msg unless ($opt_q); 1839512fe85Sahl print LOG $msg if ($opt_l); 1849512fe85Sahl} 1859512fe85Sahl 18623b5c241Stomee# Trim leading and trailing whitespace 18723b5c241Stomeesub trim { 18823b5c241Stomee my($s) = @_; 18923b5c241Stomee 19023b5c241Stomee $s =~ s/^\s*//; 19123b5c241Stomee $s =~ s/\s*$//; 19223b5c241Stomee return $s; 19323b5c241Stomee} 19423b5c241Stomee 195e77b06d2Stomee# Load exception set of skipped tests from the file at the given 196e77b06d2Stomee# pathname. The test names are assumed to be paths relative to $dt_tst, 197e77b06d2Stomee# for example: common/aggs/tst.neglquant.d, and specify tests to be 198e77b06d2Stomee# skipped. 19923b5c241Stomeesub load_exceptions { 20023b5c241Stomee my($listfile) = @_; 20123b5c241Stomee my($line) = ""; 20223b5c241Stomee 203e77b06d2Stomee %exceptions = (); 204e77b06d2Stomee if (length($listfile) > 0) { 20523b5c241Stomee exit(123) unless open(STDIN, "<$listfile"); 20623b5c241Stomee while (<STDIN>) { 20723b5c241Stomee chomp; 20823b5c241Stomee $line = $_; 20923b5c241Stomee # line is non-empty and not a comment 21023b5c241Stomee if ((length($line) > 0) && ($line =~ /^\s*[^\s#]/ )) { 21123b5c241Stomee $exceptions{trim($line)} = 1; 21223b5c241Stomee } 21323b5c241Stomee } 214e77b06d2Stomee } 21523b5c241Stomee} 21623b5c241Stomee 217e77b06d2Stomee# Return 1 if the test is found in the exception set, 0 otherwise. 21823b5c241Stomeesub is_exception { 21923b5c241Stomee my($file) = @_; 22023b5c241Stomee my($i) = -1; 22123b5c241Stomee 222e77b06d2Stomee if (scalar(keys(%exceptions)) == 0) { 223e77b06d2Stomee return 0; 224e77b06d2Stomee } 225e77b06d2Stomee 22623b5c241Stomee # hash absolute pathname after $dt_tst/ 22723b5c241Stomee $file = abs_path($file); 22823b5c241Stomee $i = index($file, $dt_tst); 22923b5c241Stomee if ($i == 0) { 23023b5c241Stomee $file = substr($file, length($dt_tst) + 1); 23123b5c241Stomee return $exceptions{$file}; 23223b5c241Stomee } 23323b5c241Stomee return 0; 23423b5c241Stomee} 23523b5c241Stomee 236e77b06d2Stomee# 237c7158ae9Stariq# Iterate over the set of test files specified on the command-line or by a find 238c7158ae9Stariq# on "$defdir/common", "$defdir/$MACH" and "$defdir/$PLATFORM" and execute each 239c7158ae9Stariq# one. If the test file is executable, we fork and exec it. If the test is a 240c7158ae9Stariq# .ksh file, we run it with $ksh_path. Otherwise we run dtrace -s on it. If 241c7158ae9Stariq# the file is named tst.* we assume it should return exit status 0. If the 242c7158ae9Stariq# file is named err.* we assume it should return exit status 1. If the file is 243c7158ae9Stariq# named err.D_[A-Z0-9]+[.*].d we use dtrace -xerrtags and examine stderr to 244c7158ae9Stariq# ensure that a matching error tag was produced. If the file is named 245c7158ae9Stariq# drp.[A-Z0-9]+[.*].d we use dtrace -xdroptags and examine stderr to ensure 246c7158ae9Stariq# that a matching drop tag was produced. If any *.out or *.err files are found 247c7158ae9Stariq# we perform output comparisons. 248e77b06d2Stomee# 249e77b06d2Stomee# run_tests takes two arguments: The first is the pathname of the dtrace 250e77b06d2Stomee# command to invoke when running the tests. The second is the pathname 251e77b06d2Stomee# of a file (may be the empty string) listing tests that ought to be 252e77b06d2Stomee# skipped (skipped tests are listed as paths relative to $dt_tst, for 253e77b06d2Stomee# example: common/aggs/tst.neglquant.d). 254e77b06d2Stomee# 255e77b06d2Stomeesub run_tests { 256e77b06d2Stomee my($dtrace, $exceptions_path) = @_; 257e77b06d2Stomee my($passed) = 0; 258e77b06d2Stomee my($bypassed) = 0; 259e77b06d2Stomee my($failed) = $errs; 260e77b06d2Stomee my($total) = 0; 261e77b06d2Stomee 262c090e5dfSBryan Cantrill die "$PNAME: $dtrace not found; aborting\n" unless (-x "$dtrace"); 263c090e5dfSBryan Cantrill logmsg("executing tests using $dtrace ...\n"); 264e77b06d2Stomee 265e77b06d2Stomee load_exceptions($exceptions_path); 266e77b06d2Stomee 267e77b06d2Stomee foreach $file (sort @files) { 268e77b06d2Stomee $file =~ m:.*/((.*)\.(\w+)):; 269e77b06d2Stomee $name = $1; 270e77b06d2Stomee $base = $2; 271e77b06d2Stomee $ext = $3; 272e77b06d2Stomee 273e77b06d2Stomee $dir = dirname($file); 274e77b06d2Stomee $isksh = 0; 275e77b06d2Stomee $tag = 0; 276e77b06d2Stomee $droptag = 0; 277e77b06d2Stomee 278e77b06d2Stomee if ($name =~ /^tst\./) { 279e77b06d2Stomee $isksh = ($ext eq 'ksh'); 280e77b06d2Stomee $status = 0; 281e77b06d2Stomee } elsif ($name =~ /^err\.(D_[A-Z0-9_]+)\./) { 282e77b06d2Stomee $status = 1; 283e77b06d2Stomee $tag = $1; 284e77b06d2Stomee } elsif ($name =~ /^err\./) { 285e77b06d2Stomee $status = 1; 286e77b06d2Stomee } elsif ($name =~ /^drp\.([A-Z0-9_]+)\./) { 287e77b06d2Stomee $status = 0; 288e77b06d2Stomee $droptag = $1; 289e77b06d2Stomee } else { 290e77b06d2Stomee errmsg("ERROR: $file is not a valid test file name\n"); 291e77b06d2Stomee next; 292e77b06d2Stomee } 293e77b06d2Stomee 294e77b06d2Stomee $fullname = "$dir/$name"; 295e77b06d2Stomee $exe = "$dir/$base.exe"; 296e77b06d2Stomee $exe_pid = -1; 297e77b06d2Stomee 298e77b06d2Stomee if ($opt_a && ($status != 0 || $tag != 0 || $droptag != 0 || 299e77b06d2Stomee -x $exe || $isksh || -x $fullname)) { 300e77b06d2Stomee $bypassed++; 301e77b06d2Stomee next; 302e77b06d2Stomee } 303e77b06d2Stomee 304e77b06d2Stomee if (!$opt_f && is_exception("$dir/$name")) { 305e77b06d2Stomee $bypassed++; 306e77b06d2Stomee next; 307e77b06d2Stomee } 308e77b06d2Stomee 309e77b06d2Stomee if (!$isksh && -x $exe) { 310e77b06d2Stomee if (($exe_pid = fork()) == -1) { 311e77b06d2Stomee errmsg( 312e77b06d2Stomee "ERROR: failed to fork to run $exe: $!\n"); 313e77b06d2Stomee next; 314e77b06d2Stomee } 315e77b06d2Stomee 316e77b06d2Stomee if ($exe_pid == 0) { 317e77b06d2Stomee open(STDIN, '</dev/null'); 318e77b06d2Stomee 319e77b06d2Stomee exec($exe); 320e77b06d2Stomee 321e77b06d2Stomee warn "ERROR: failed to exec $exe: $!\n"; 322e77b06d2Stomee } 323e77b06d2Stomee } 324e77b06d2Stomee 325e77b06d2Stomee logmsg("testing $file ... "); 326e77b06d2Stomee 327e77b06d2Stomee if (($pid = fork()) == -1) { 328e77b06d2Stomee errmsg("ERROR: failed to fork to run test $file: $!\n"); 329e77b06d2Stomee next; 330e77b06d2Stomee } 331e77b06d2Stomee 332e77b06d2Stomee if ($pid == 0) { 333e77b06d2Stomee open(STDIN, '</dev/null'); 334e77b06d2Stomee exit(125) unless open(STDOUT, ">$opt_d/$$.out"); 335e77b06d2Stomee exit(125) unless open(STDERR, ">$opt_d/$$.err"); 336e77b06d2Stomee 337e77b06d2Stomee unless (chdir($dir)) { 338e77b06d2Stomee warn "ERROR: failed to chdir for $file: $!\n"; 339e77b06d2Stomee exit(126); 340e77b06d2Stomee } 341e77b06d2Stomee 342e77b06d2Stomee push(@dtrace_argv, '-xerrtags') if ($tag); 343e77b06d2Stomee push(@dtrace_argv, '-xdroptags') if ($droptag); 344e77b06d2Stomee push(@dtrace_argv, $exe_pid) if ($exe_pid != -1); 345e77b06d2Stomee 346e77b06d2Stomee if ($isksh) { 347e77b06d2Stomee exit(123) unless open(STDIN, "<$name"); 348e77b06d2Stomee exec("$ksh_path /dev/stdin $dtrace"); 349e77b06d2Stomee } elsif (-x $name) { 350e77b06d2Stomee warn "ERROR: $name is executable\n"; 351e77b06d2Stomee exit(1); 352e77b06d2Stomee } else { 353e77b06d2Stomee if ($tag == 0 && $status == $0 && $opt_a) { 354e77b06d2Stomee push(@dtrace_argv, '-A'); 355e77b06d2Stomee } 356e77b06d2Stomee 357e77b06d2Stomee push(@dtrace_argv, '-C'); 358e77b06d2Stomee push(@dtrace_argv, '-s'); 359e77b06d2Stomee push(@dtrace_argv, $name); 360e77b06d2Stomee exec($dtrace, @dtrace_argv); 361e77b06d2Stomee } 362e77b06d2Stomee 363e77b06d2Stomee warn "ERROR: failed to exec for $file: $!\n"; 364e77b06d2Stomee exit(127); 365e77b06d2Stomee } 366e77b06d2Stomee 367e77b06d2Stomee if (waitpid($pid, 0) == -1) { 368e77b06d2Stomee errmsg("ERROR: timed out waiting for $file\n"); 369e77b06d2Stomee kill(9, $exe_pid) if ($exe_pid != -1); 370e77b06d2Stomee kill(9, $pid); 371e77b06d2Stomee next; 372e77b06d2Stomee } 373e77b06d2Stomee 374e77b06d2Stomee kill(9, $exe_pid) if ($exe_pid != -1); 375e77b06d2Stomee 376e77b06d2Stomee if ($tag == 0 && $status == $0 && $opt_a) { 377e77b06d2Stomee # 378e77b06d2Stomee # We can chuck the earler output. 379e77b06d2Stomee # 380e77b06d2Stomee unlink($pid . '.out'); 381e77b06d2Stomee unlink($pid . '.err'); 382e77b06d2Stomee 383e77b06d2Stomee # 384e77b06d2Stomee # This is an anonymous enabling. We need to get 385e77b06d2Stomee # the module unloaded. 386e77b06d2Stomee # 387e77b06d2Stomee system("dtrace -ae 1> /dev/null 2> /dev/null"); 388e77b06d2Stomee system("svcadm disable -s " . 389e77b06d2Stomee "svc:/network/nfs/mapid:default"); 390e77b06d2Stomee system("modunload -i 0 ; modunload -i 0 ; " . 391e77b06d2Stomee "modunload -i 0"); 392e77b06d2Stomee if (!system("modinfo | grep dtrace")) { 393e77b06d2Stomee warn "ERROR: couldn't unload dtrace\n"; 394e77b06d2Stomee system("svcadm enable " . 395e77b06d2Stomee "-s svc:/network/nfs/mapid:default"); 396e77b06d2Stomee exit(124); 397e77b06d2Stomee } 398e77b06d2Stomee 399e77b06d2Stomee # 400e77b06d2Stomee # DTrace is gone. Now update_drv(1M), and rip 401e77b06d2Stomee # everything out again. 402e77b06d2Stomee # 403e77b06d2Stomee system("update_drv dtrace"); 404e77b06d2Stomee system("dtrace -ae 1> /dev/null 2> /dev/null"); 405e77b06d2Stomee system("modunload -i 0 ; modunload -i 0 ; " . 406e77b06d2Stomee "modunload -i 0"); 407e77b06d2Stomee if (!system("modinfo | grep dtrace")) { 408e77b06d2Stomee warn "ERROR: couldn't unload dtrace\n"; 409e77b06d2Stomee system("svcadm enable " . 410e77b06d2Stomee "-s svc:/network/nfs/mapid:default"); 411e77b06d2Stomee exit(124); 412e77b06d2Stomee } 413e77b06d2Stomee 414e77b06d2Stomee # 415e77b06d2Stomee # Now bring DTrace back in. 416e77b06d2Stomee # 417e77b06d2Stomee system("sync ; sync"); 418e77b06d2Stomee system("dtrace -l -n bogusprobe 1> /dev/null " . 419e77b06d2Stomee "2> /dev/null"); 420e77b06d2Stomee system("svcadm enable -s " . 421e77b06d2Stomee "svc:/network/nfs/mapid:default"); 422e77b06d2Stomee 423e77b06d2Stomee # 424e77b06d2Stomee # That should have caused DTrace to reload with 425e77b06d2Stomee # the new configuration file. Now we can try to 426e77b06d2Stomee # snag our anonymous state. 427e77b06d2Stomee # 428e77b06d2Stomee if (($pid = fork()) == -1) { 429e77b06d2Stomee errmsg("ERROR: failed to fork to run " . 430e77b06d2Stomee "test $file: $!\n"); 431e77b06d2Stomee next; 432e77b06d2Stomee } 433e77b06d2Stomee 434e77b06d2Stomee if ($pid == 0) { 435e77b06d2Stomee open(STDIN, '</dev/null'); 436e77b06d2Stomee exit(125) unless open(STDOUT, ">$opt_d/$$.out"); 437e77b06d2Stomee exit(125) unless open(STDERR, ">$opt_d/$$.err"); 438e77b06d2Stomee 439e77b06d2Stomee push(@dtrace_argv, '-a'); 440e77b06d2Stomee 441e77b06d2Stomee unless (chdir($dir)) { 442e77b06d2Stomee warn "ERROR: failed to chdir " . 443e77b06d2Stomee "for $file: $!\n"; 444e77b06d2Stomee exit(126); 445e77b06d2Stomee } 446e77b06d2Stomee 447e77b06d2Stomee exec($dtrace, @dtrace_argv); 448e77b06d2Stomee warn "ERROR: failed to exec for $file: $!\n"; 449e77b06d2Stomee exit(127); 450e77b06d2Stomee } 451e77b06d2Stomee 452e77b06d2Stomee if (waitpid($pid, 0) == -1) { 453e77b06d2Stomee errmsg("ERROR: timed out waiting for $file\n"); 454e77b06d2Stomee kill(9, $pid); 455e77b06d2Stomee next; 456e77b06d2Stomee } 457e77b06d2Stomee } 458e77b06d2Stomee 459e77b06d2Stomee logmsg("[$pid]\n"); 460e77b06d2Stomee $wstat = $?; 461e77b06d2Stomee $wifexited = ($wstat & 0xFF) == 0; 462e77b06d2Stomee $wexitstat = ($wstat >> 8) & 0xFF; 463e77b06d2Stomee $wtermsig = ($wstat & 0x7F); 464e77b06d2Stomee 465e77b06d2Stomee if (!$wifexited) { 466e77b06d2Stomee fail("died from signal $wtermsig"); 467e77b06d2Stomee next; 468e77b06d2Stomee } 469e77b06d2Stomee 470e77b06d2Stomee if ($wexitstat == 125) { 471e77b06d2Stomee die "$PNAME: failed to create output file in $opt_d " . 472e77b06d2Stomee "(cd elsewhere or use -d)\n"; 473e77b06d2Stomee } 474e77b06d2Stomee 475e77b06d2Stomee if ($wexitstat != $status) { 476e77b06d2Stomee fail("returned $wexitstat instead of $status"); 477e77b06d2Stomee next; 478e77b06d2Stomee } 479e77b06d2Stomee 480e77b06d2Stomee if (-f "$file.out" && 481e77b06d2Stomee system("cmp -s $file.out $opt_d/$pid.out") != 0) { 482e77b06d2Stomee fail("stdout mismatch", "$pid.out"); 483e77b06d2Stomee next; 484e77b06d2Stomee } 485e77b06d2Stomee 486e77b06d2Stomee if (-f "$file.err" && 487e77b06d2Stomee system("cmp -s $file.err $opt_d/$pid.err") != 0) { 488e77b06d2Stomee fail("stderr mismatch: see $pid.err"); 489e77b06d2Stomee next; 490e77b06d2Stomee } 491e77b06d2Stomee 492e77b06d2Stomee if ($tag) { 493e77b06d2Stomee open(TSTERR, "<$opt_d/$pid.err"); 494e77b06d2Stomee $tsterr = <TSTERR>; 495e77b06d2Stomee close(TSTERR); 496e77b06d2Stomee 497e77b06d2Stomee unless ($tsterr =~ /: \[$tag\] line \d+:/) { 498e77b06d2Stomee fail("errtag mismatch: see $pid.err"); 499e77b06d2Stomee next; 500e77b06d2Stomee } 501e77b06d2Stomee } 502e77b06d2Stomee 503e77b06d2Stomee if ($droptag) { 504e77b06d2Stomee $found = 0; 505e77b06d2Stomee open(TSTERR, "<$opt_d/$pid.err"); 506e77b06d2Stomee 507e77b06d2Stomee while (<TSTERR>) { 508e77b06d2Stomee if (/\[$droptag\] /) { 509e77b06d2Stomee $found = 1; 510e77b06d2Stomee last; 511e77b06d2Stomee } 512e77b06d2Stomee } 513e77b06d2Stomee 514e77b06d2Stomee close (TSTERR); 515e77b06d2Stomee 516e77b06d2Stomee unless ($found) { 517e77b06d2Stomee fail("droptag mismatch: see $pid.err"); 518e77b06d2Stomee next; 519e77b06d2Stomee } 520e77b06d2Stomee } 521e77b06d2Stomee 522e77b06d2Stomee unless ($opt_s) { 523e77b06d2Stomee unlink($pid . '.out'); 524e77b06d2Stomee unlink($pid . '.err'); 525e77b06d2Stomee } 526e77b06d2Stomee } 527e77b06d2Stomee 528e77b06d2Stomee if ($opt_a) { 529e77b06d2Stomee # 530e77b06d2Stomee # If we're running with anonymous enablings, we need to 531e77b06d2Stomee # restore the .conf file. 532e77b06d2Stomee # 533e77b06d2Stomee system("dtrace -A 1> /dev/null 2> /dev/null"); 534e77b06d2Stomee system("dtrace -ae 1> /dev/null 2> /dev/null"); 535e77b06d2Stomee system("modunload -i 0 ; modunload -i 0 ; modunload -i 0"); 536e77b06d2Stomee system("update_drv dtrace"); 537e77b06d2Stomee } 538e77b06d2Stomee 539e77b06d2Stomee $total = scalar(@files); 540e77b06d2Stomee $failed = $errs - $failed; 541e77b06d2Stomee $passed = ($total - $failed - $bypassed); 542e77b06d2Stomee $results{$dtrace} = { 543e77b06d2Stomee "passed" => $passed, 544e77b06d2Stomee "bypassed" => $bypassed, 545e77b06d2Stomee "failed" => $failed, 546e77b06d2Stomee "total" => $total 547e77b06d2Stomee }; 548e77b06d2Stomee} 549e77b06d2Stomee 55023b5c241Stomeedie $USAGE unless (getopts($OPTSTR)); 5519512fe85Sahlusage() if ($opt_h); 5529512fe85Sahl 5539512fe85Sahlforeach $arg (@ARGV) { 5549512fe85Sahl if (-f $arg) { 5559512fe85Sahl push(@files, $arg); 5569512fe85Sahl } elsif (-d $arg) { 5579512fe85Sahl find(\&wanted, $arg); 5589512fe85Sahl } else { 5599512fe85Sahl die "$PNAME: $arg is not a valid file or directory\n"; 5609512fe85Sahl } 5619512fe85Sahl} 5629512fe85Sahl 56323b5c241Stomee$dt_tst = '/opt/SUNWdtrt/tst'; 56423b5c241Stomee$dt_bin = '/opt/SUNWdtrt/bin'; 56523b5c241Stomee$defdir = -d $dt_tst ? $dt_tst : '.'; 56623b5c241Stomee$bindir = -d $dt_bin ? $dt_bin : '.'; 5679512fe85Sahl 568c090e5dfSBryan Cantrillif (!$opt_F) { 569c090e5dfSBryan Cantrill my @dependencies = ("gcc", "make", "java", "perl"); 570c090e5dfSBryan Cantrill 571c090e5dfSBryan Cantrill for my $dep (@dependencies) { 572c090e5dfSBryan Cantrill if (!inpath($dep)) { 573c090e5dfSBryan Cantrill die "$PNAME: '$dep' not found (use -F to force run)\n"; 574c090e5dfSBryan Cantrill } 575c090e5dfSBryan Cantrill } 576c090e5dfSBryan Cantrill} 577c090e5dfSBryan Cantrill 5789512fe85Sahlfind(\&wanted, "$defdir/common") if (scalar(@ARGV) == 0); 5799512fe85Sahlfind(\&wanted, "$defdir/$MACH") if (scalar(@ARGV) == 0); 580c7158ae9Stariqfind(\&wanted, "$defdir/$PLATFORM") if (scalar(@ARGV) == 0); 581c090e5dfSBryan Cantrill 5829512fe85Sahldie $USAGE if (scalar(@files) == 0); 5839512fe85Sahl 584e77b06d2Stomee$dtrace_path = '/usr/sbin/dtrace'; 585e77b06d2Stomee$jdtrace_path = "$bindir/jdtrace"; 586e77b06d2Stomee 587e77b06d2Stomee%exception_lists = ("$jdtrace_path" => "$bindir/exception.lst"); 588e77b06d2Stomee 589e77b06d2Stomeeif ($opt_j || $opt_n || $opt_i) { 590e77b06d2Stomee @dtrace_cmds = (); 591e77b06d2Stomee push(@dtrace_cmds, $dtrace_path) if ($opt_n); 592e77b06d2Stomee push(@dtrace_cmds, $jdtrace_path) if ($opt_j); 593e77b06d2Stomee push(@dtrace_cmds, "/usr/sbin/$opt_i/dtrace") if ($opt_i); 594e77b06d2Stomee} else { 595c090e5dfSBryan Cantrill @dtrace_cmds = ($dtrace_path); 596e77b06d2Stomee} 597e77b06d2Stomee 5989512fe85Sahlif ($opt_d) { 5999512fe85Sahl die "$PNAME: -d arg must be absolute path\n" unless ($opt_d =~ /^\//); 6009512fe85Sahl die "$PNAME: -d arg $opt_d is not a directory\n" unless (-d "$opt_d"); 6019512fe85Sahl system("coreadm -p $opt_d/%p.core"); 6029512fe85Sahl} else { 6039512fe85Sahl my $dir = getcwd; 6049512fe85Sahl system("coreadm -p $dir/%p.core"); 6059512fe85Sahl $opt_d = '.'; 6069512fe85Sahl} 6079512fe85Sahl 6089512fe85Sahlif ($opt_x) { 6099512fe85Sahl push(@dtrace_argv, '-x'); 6109512fe85Sahl push(@dtrace_argv, $opt_x); 6119512fe85Sahl} 6129512fe85Sahl 6139512fe85Sahldie "$PNAME: failed to open $PNAME.$$.log: $!\n" 6149512fe85Sahl unless (!$opt_l || open(LOG, ">$PNAME.$$.log")); 6159512fe85Sahl 616*e5803b76SAdam H. Leventhal$ENV{'DTRACE_DEBUG_REGSET'} = 'true'; 617*e5803b76SAdam H. Leventhal 6189512fe85Sahlif ($opt_g) { 6199512fe85Sahl $ENV{'UMEM_DEBUG'} = 'default,verbose'; 6209512fe85Sahl $ENV{'UMEM_LOGGING'} = 'fail,contents'; 6219512fe85Sahl $ENV{'LD_PRELOAD'} = 'libumem.so'; 6229512fe85Sahl} 6239512fe85Sahl 6249512fe85Sahlif ($opt_b) { 6259512fe85Sahl logmsg("badioctl'ing ... "); 6269512fe85Sahl 6279512fe85Sahl if (($badioctl = fork()) == -1) { 6289512fe85Sahl errmsg("ERROR: failed to fork to run badioctl: $!\n"); 6299512fe85Sahl next; 6309512fe85Sahl } 6319512fe85Sahl 6329512fe85Sahl if ($badioctl == 0) { 6339512fe85Sahl open(STDIN, '</dev/null'); 6349512fe85Sahl exit(125) unless open(STDOUT, ">$opt_d/$$.out"); 6359512fe85Sahl exit(125) unless open(STDERR, ">$opt_d/$$.err"); 6369512fe85Sahl 6379512fe85Sahl exec($bindir . "/badioctl"); 6389512fe85Sahl warn "ERROR: failed to exec badioctl: $!\n"; 6399512fe85Sahl exit(127); 6409512fe85Sahl } 6419512fe85Sahl 6429512fe85Sahl 6439512fe85Sahl logmsg("[$badioctl]\n"); 6449512fe85Sahl 6459512fe85Sahl # 6469512fe85Sahl # If we're going to be bad, we're just going to iterate over each 6479512fe85Sahl # test file. 6489512fe85Sahl # 6499512fe85Sahl foreach $file (sort @files) { 6509512fe85Sahl ($name = $file) =~ s:.*/::; 6519512fe85Sahl $dir = dirname($file); 6529512fe85Sahl 6539512fe85Sahl if (!($name =~ /^tst\./ && $name =~ /\.d$/)) { 6549512fe85Sahl next; 6559512fe85Sahl } 6569512fe85Sahl 6579512fe85Sahl logmsg("baddof'ing $file ... "); 6589512fe85Sahl 6599512fe85Sahl if (($pid = fork()) == -1) { 6609512fe85Sahl errmsg("ERROR: failed to fork to run baddof: $!\n"); 6619512fe85Sahl next; 6629512fe85Sahl } 6639512fe85Sahl 6649512fe85Sahl if ($pid == 0) { 6659512fe85Sahl open(STDIN, '</dev/null'); 6669512fe85Sahl exit(125) unless open(STDOUT, ">$opt_d/$$.out"); 6679512fe85Sahl exit(125) unless open(STDERR, ">$opt_d/$$.err"); 6689512fe85Sahl 6699512fe85Sahl unless (chdir($dir)) { 6709512fe85Sahl warn "ERROR: failed to chdir for $file: $!\n"; 6719512fe85Sahl exit(126); 6729512fe85Sahl } 6739512fe85Sahl 6749512fe85Sahl exec($bindir . "/baddof", $name); 6759512fe85Sahl 6769512fe85Sahl warn "ERROR: failed to exec for $file: $!\n"; 6779512fe85Sahl exit(127); 6789512fe85Sahl } 6799512fe85Sahl 6809512fe85Sahl sleep 60; 6819512fe85Sahl kill(9, $pid); 6829512fe85Sahl waitpid($pid, 0); 6839512fe85Sahl 6849512fe85Sahl logmsg("[$pid]\n"); 6859512fe85Sahl 6869512fe85Sahl unless ($opt_s) { 6879512fe85Sahl unlink($pid . '.out'); 6889512fe85Sahl unlink($pid . '.err'); 6899512fe85Sahl } 6909512fe85Sahl } 6919512fe85Sahl 6929512fe85Sahl kill(9, $badioctl); 6939512fe85Sahl waitpid($badioctl, 0); 6949512fe85Sahl 6959512fe85Sahl unless ($opt_s) { 6969512fe85Sahl unlink($badioctl . '.out'); 6979512fe85Sahl unlink($badioctl . '.err'); 6989512fe85Sahl } 6999512fe85Sahl 7009512fe85Sahl exit(0); 7019512fe85Sahl} 7029512fe85Sahl 7039512fe85Sahl# 704e77b06d2Stomee# Run all the tests specified on the command-line (the entire test suite 705e77b06d2Stomee# by default) once for each dtrace command tested, skipping any tests 706e77b06d2Stomee# not valid for that command. 7079512fe85Sahl# 708e77b06d2Stomeeforeach $dtrace_cmd (@dtrace_cmds) { 709e77b06d2Stomee run_tests($dtrace_cmd, $exception_lists{$dtrace_cmd}); 7109512fe85Sahl} 7119512fe85Sahl 7129512fe85Sahl$opt_q = 0; # force final summary to appear regardless of -q option 7139512fe85Sahl 7149512fe85Sahllogmsg("\n==== TEST RESULTS ====\n"); 715e77b06d2Stomeeforeach $key (keys %results) { 716e77b06d2Stomee my $passed = $results{$key}{"passed"}; 717e77b06d2Stomee my $bypassed = $results{$key}{"bypassed"}; 718e77b06d2Stomee my $failed = $results{$key}{"failed"}; 719e77b06d2Stomee my $total = $results{$key}{"total"}; 7209512fe85Sahl 721e77b06d2Stomee logmsg("\n mode: " . $key . "\n"); 722e77b06d2Stomee logmsg(" passed: " . $passed . "\n"); 7239512fe85Sahl if ($bypassed) { 7249512fe85Sahl logmsg(" bypassed: " . $bypassed . "\n"); 7259512fe85Sahl } 726e77b06d2Stomee logmsg(" failed: " . $failed . "\n"); 727e77b06d2Stomee logmsg(" total: " . $total . "\n"); 7289512fe85Sahl} 7299512fe85Sahl 7309512fe85Sahlexit($errs != 0); 731