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