1*05b00f60SXin Li#!/usr/bin/env perl 2*05b00f60SXin Li 3*05b00f60SXin Li# 4*05b00f60SXin Li# Were we told where to find tcpdump? 5*05b00f60SXin Li# 6*05b00f60SXin Liif (!($TCPDUMP = $ENV{TCPDUMP_BIN})) { 7*05b00f60SXin Li # 8*05b00f60SXin Li # No. Use the appropriate path. 9*05b00f60SXin Li # 10*05b00f60SXin Li if ($^O eq 'MSWin32') { 11*05b00f60SXin Li # 12*05b00f60SXin Li # XXX - assume, for now, a Visual Studio debug build, so that 13*05b00f60SXin Li # tcpdump is in the Debug subdirectory. 14*05b00f60SXin Li # 15*05b00f60SXin Li $TCPDUMP = "Debug\\tcpdump" 16*05b00f60SXin Li } else { 17*05b00f60SXin Li $TCPDUMP = "./tcpdump" 18*05b00f60SXin Li } 19*05b00f60SXin Li} 20*05b00f60SXin Li 21*05b00f60SXin Li# 22*05b00f60SXin Li# Make true and false work as Booleans. 23*05b00f60SXin Li# 24*05b00f60SXin Liuse constant true => 1; 25*05b00f60SXin Liuse constant false => 0; 26*05b00f60SXin Li 27*05b00f60SXin Liuse File::Basename; 28*05b00f60SXin Liuse POSIX qw( WEXITSTATUS WIFEXITED); 29*05b00f60SXin Liuse Cwd qw(abs_path getcwd); 30*05b00f60SXin Liuse File::Path qw(mkpath); # mkpath works with ancient perl, as well as newer perl 31*05b00f60SXin Liuse File::Spec; 32*05b00f60SXin Liuse Data::Dumper; # for debugging. 33*05b00f60SXin Li 34*05b00f60SXin Li# these are created in the directory where we are run, which might be 35*05b00f60SXin Li# a build directory. 36*05b00f60SXin Limy $newdir = "tests/NEW"; 37*05b00f60SXin Limy $diffdir= "tests/DIFF"; 38*05b00f60SXin Limkpath($newdir); 39*05b00f60SXin Limkpath($diffdir); 40*05b00f60SXin Limy $origdir = getcwd(); 41*05b00f60SXin Limy $srcdir = $ENV{'srcdir'} || "."; 42*05b00f60SXin Li# Default to unified diff and allow to fall back to basic diff if necessary. 43*05b00f60SXin Limy $diff_flags = defined $ENV{'DIFF_FLAGS'} ? $ENV{'DIFF_FLAGS'} : '-u'; 44*05b00f60SXin Li 45*05b00f60SXin Li# 46*05b00f60SXin Li# Force UTC, so time stamps are printed in a standard time zone, and 47*05b00f60SXin Li# tests don't have to be run in the time zone in which the output 48*05b00f60SXin Li# file was generated. 49*05b00f60SXin Li# 50*05b00f60SXin Li$ENV{'TZ'}='GMT0'; 51*05b00f60SXin Li 52*05b00f60SXin Li# 53*05b00f60SXin Li# Get the tests directory from $0. 54*05b00f60SXin Li# 55*05b00f60SXin Limy $testsdir = dirname($0); 56*05b00f60SXin Li 57*05b00f60SXin Li# 58*05b00f60SXin Li# Convert it to an absolute path, so it works even after we do a cd. 59*05b00f60SXin Li# 60*05b00f60SXin Li$testsdir = abs_path($testsdir); 61*05b00f60SXin Liprint "Running tests from ${testsdir}\n"; 62*05b00f60SXin Liprint "with ${TCPDUMP}, version:\n"; 63*05b00f60SXin Lisystem "${TCPDUMP} --version"; 64*05b00f60SXin Li 65*05b00f60SXin Liunshift(@INC, $testsdir); 66*05b00f60SXin Li 67*05b00f60SXin Li$passedcount = 0; 68*05b00f60SXin Li$failedcount = 0; 69*05b00f60SXin Li# 70*05b00f60SXin Limy $failureoutput=$origdir . "/tests/failure-outputs.txt"; 71*05b00f60SXin Li 72*05b00f60SXin Li# truncate the output file 73*05b00f60SXin Liopen(FAILUREOUTPUT, ">" . $failureoutput); 74*05b00f60SXin Liclose(FAILUREOUTPUT); 75*05b00f60SXin Li 76*05b00f60SXin Li$confighhash = undef; 77*05b00f60SXin Li 78*05b00f60SXin Lisub showfile { 79*05b00f60SXin Li local($path) = @_; 80*05b00f60SXin Li 81*05b00f60SXin Li # 82*05b00f60SXin Li # XXX - just do this directly in Perl? 83*05b00f60SXin Li # 84*05b00f60SXin Li if ($^O eq 'MSWin32') { 85*05b00f60SXin Li my $winpath = File::Spec->canonpath($path); 86*05b00f60SXin Li system "type $winpath"; 87*05b00f60SXin Li } else { 88*05b00f60SXin Li system "cat $path"; 89*05b00f60SXin Li } 90*05b00f60SXin Li} 91*05b00f60SXin Li 92*05b00f60SXin Lisub runtest { 93*05b00f60SXin Li local($name, $input, $output, $options) = @_; 94*05b00f60SXin Li my $r; 95*05b00f60SXin Li 96*05b00f60SXin Li $outputbase = basename($output); 97*05b00f60SXin Li my $coredump = false; 98*05b00f60SXin Li my $status = 0; 99*05b00f60SXin Li my $linecount = 0; 100*05b00f60SXin Li my $rawstderrlog = "tests/NEW/${outputbase}.raw.stderr"; 101*05b00f60SXin Li my $stderrlog = "tests/NEW/${outputbase}.stderr"; 102*05b00f60SXin Li my $diffstat = 0; 103*05b00f60SXin Li my $errdiffstat = 0; 104*05b00f60SXin Li 105*05b00f60SXin Li # we used to do this as a nice pipeline, but the problem is that $r fails to 106*05b00f60SXin Li # to be set properly if the tcpdump core dumps. 107*05b00f60SXin Li # 108*05b00f60SXin Li # Furthermore, on Windows, fc can't read the standard input, so we 109*05b00f60SXin Li # can't do it as a pipeline in any case. 110*05b00f60SXin Li $r = system "$TCPDUMP -# -n -r $input $options >tests/NEW/${outputbase} 2>${rawstderrlog}"; 111*05b00f60SXin Li if($r != 0) { 112*05b00f60SXin Li # 113*05b00f60SXin Li # Something other than "tcpdump opened the file, read it, and 114*05b00f60SXin Li # dissected all the packets". What happened? 115*05b00f60SXin Li # 116*05b00f60SXin Li # We write out an exit status after whatever the subprocess 117*05b00f60SXin Li # wrote out, so it shows up when we diff the expected output 118*05b00f60SXin Li # with it. 119*05b00f60SXin Li # 120*05b00f60SXin Li open(OUTPUT, ">>"."tests/NEW/$outputbase") || die "fail to open $outputbase\n"; 121*05b00f60SXin Li if($r == -1) { 122*05b00f60SXin Li # failed to start due to error. 123*05b00f60SXin Li $status = $!; 124*05b00f60SXin Li printf OUTPUT "FAILED TO RUN: status: %d\n", $status; 125*05b00f60SXin Li } else { 126*05b00f60SXin Li if ($^O eq 'MSWin32' or $^O eq 'msys') { 127*05b00f60SXin Li # 128*05b00f60SXin Li # On Windows, the return value of system is the lower 8 129*05b00f60SXin Li # bits of the exit status of the process, shifted left 130*05b00f60SXin Li # 8 bits. 131*05b00f60SXin Li # 132*05b00f60SXin Li # If the process crashed, rather than exiting, the 133*05b00f60SXin Li # exit status will be one of the EXCEPTION_ values 134*05b00f60SXin Li # listed in the documentation for the GetExceptionCode() 135*05b00f60SXin Li # macro. 136*05b00f60SXin Li # 137*05b00f60SXin Li # Those are defined as STATUS_ values, which should have 138*05b00f60SXin Li # 0xC in the topmost 4 bits (being fatal error 139*05b00f60SXin Li # statuses); some of them have a value that fits in 140*05b00f60SXin Li # the lower 8 bits. We could, I guess, assume that 141*05b00f60SXin Li # any value that 1) isn't returned by tcpdump and 2) 142*05b00f60SXin Li # corresponds to the lower 8 bits of a STATUS_ value 143*05b00f60SXin Li # used as an EXCEPTION_ value indicates that tcpdump 144*05b00f60SXin Li # exited with that exception. 145*05b00f60SXin Li # 146*05b00f60SXin Li # However, as we're running tcpdump with system, which 147*05b00f60SXin Li # runs the command through cmd.exe, and as cmd.exe 148*05b00f60SXin Li # doesn't map the command's exit code to its own exit 149*05b00f60SXin Li # code in any straightforward manner, we can't get 150*05b00f60SXin Li # that information in any case, so there's no point 151*05b00f60SXin Li # in trying to interpret it in that fashion. 152*05b00f60SXin Li # 153*05b00f60SXin Li $status = $r >> 8; 154*05b00f60SXin Li } else { 155*05b00f60SXin Li # 156*05b00f60SXin Li # On UN*Xes, the return status is a POSIX as filled in 157*05b00f60SXin Li # by wait() or waitpid(). 158*05b00f60SXin Li # 159*05b00f60SXin Li # POSIX offers some calls for analyzing it, such as 160*05b00f60SXin Li # WIFSIGNALED() to test whether it indicates that the 161*05b00f60SXin Li # process was terminated by a signal, WTERMSIG() to 162*05b00f60SXin Li # get the signal number from it, WIFEXITED() to test 163*05b00f60SXin Li # whether it indicates that the process exited normally, 164*05b00f60SXin Li # and WEXITSTATUS() to get the exit status from it. 165*05b00f60SXin Li # 166*05b00f60SXin Li # POSIX doesn't standardize core dumps, so the POSIX 167*05b00f60SXin Li # calls can't test whether a core dump occurred. 168*05b00f60SXin Li # However, all the UN*Xes we are likely to encounter 169*05b00f60SXin Li # follow Research UNIX in this regard, with the exit 170*05b00f60SXin Li # status containing either 0 or a signal number in 171*05b00f60SXin Li # the lower 7 bits, with 0 meaning "exited rather 172*05b00f60SXin Li # than being terminated by a signal", the "core dumped" 173*05b00f60SXin Li # flag in the 0x80 bit, and, if the signal number is 174*05b00f60SXin Li # 0, the exit status in the next 8 bits up. 175*05b00f60SXin Li # 176*05b00f60SXin Li # This should be cleaned up to use the POSIX calls 177*05b00f60SXin Li # from the Perl library - and to define an additional 178*05b00f60SXin Li # WCOREDUMP() call to test the "core dumped" bit and 179*05b00f60SXin Li # use that. 180*05b00f60SXin Li # 181*05b00f60SXin Li # But note also that, as we're running tcpdump with 182*05b00f60SXin Li # system, which runs the command through a shell, if 183*05b00f60SXin Li # tcpdump crashes, we'll only know that if the shell 184*05b00f60SXin Li # maps the signal indication and uses that as its 185*05b00f60SXin Li # exit status. 186*05b00f60SXin Li # 187*05b00f60SXin Li # The good news is that the Bourne shell, and compatible 188*05b00f60SXin Li # shells, have traditionally done that. If the process 189*05b00f60SXin Li # for which the shell reports the exit status terminates 190*05b00f60SXin Li # with a signal, it adds 128 to the signal number and 191*05b00f60SXin Li # returns that as its exit status. (This is why the 192*05b00f60SXin Li # "this is now working right" behavior described in a 193*05b00f60SXin Li # comment below is occurring.) 194*05b00f60SXin Li # 195*05b00f60SXin Li # As tcpdump itself never returns with an exit status 196*05b00f60SXin Li # >= 128, we can try checking for an exit status with 197*05b00f60SXin Li # the 0x80 bit set and, if we have one, get the signal 198*05b00f60SXin Li # number from the lower 7 bits of the exit status. We 199*05b00f60SXin Li # can't get the "core dumped" indication from the 200*05b00f60SXin Li # shell's exit status; all we can do is check whether 201*05b00f60SXin Li # there's a core file. 202*05b00f60SXin Li # 203*05b00f60SXin Li if( $r & 128 ) { 204*05b00f60SXin Li $coredump = $r & 127; 205*05b00f60SXin Li } 206*05b00f60SXin Li if( WIFEXITED($r)) { 207*05b00f60SXin Li $status = WEXITSTATUS($r); 208*05b00f60SXin Li } 209*05b00f60SXin Li } 210*05b00f60SXin Li 211*05b00f60SXin Li if($coredump || $status) { 212*05b00f60SXin Li printf OUTPUT "EXIT CODE %08x: dump:%d code: %d\n", $r, $coredump, $status; 213*05b00f60SXin Li } else { 214*05b00f60SXin Li printf OUTPUT "EXIT CODE %08x\n", $r; 215*05b00f60SXin Li } 216*05b00f60SXin Li $r = 0; 217*05b00f60SXin Li } 218*05b00f60SXin Li close(OUTPUT); 219*05b00f60SXin Li } 220*05b00f60SXin Li if($r == 0) { 221*05b00f60SXin Li # 222*05b00f60SXin Li # Compare tcpdump's output with what we think it should be. 223*05b00f60SXin Li # If tcpdump failed to produce output, we've produced our own 224*05b00f60SXin Li # "output" above, with the exit status. 225*05b00f60SXin Li # 226*05b00f60SXin Li if ($^O eq 'MSWin32') { 227*05b00f60SXin Li my $winoutput = File::Spec->canonpath($output); 228*05b00f60SXin Li $r = system "fc /lb1000 /t /1 $winoutput tests\\NEW\\$outputbase >tests\\DIFF\\$outputbase.diff"; 229*05b00f60SXin Li $diffstat = $r >> 8; 230*05b00f60SXin Li } else { 231*05b00f60SXin Li $r = system "diff $diff_flags $output tests/NEW/$outputbase >tests/DIFF/$outputbase.diff"; 232*05b00f60SXin Li $diffstat = WEXITSTATUS($r); 233*05b00f60SXin Li } 234*05b00f60SXin Li } 235*05b00f60SXin Li 236*05b00f60SXin Li # process the standard error file, sanitize "reading from" line, 237*05b00f60SXin Li # and count lines 238*05b00f60SXin Li $linecount = 0; 239*05b00f60SXin Li open(ERRORRAW, "<" . $rawstderrlog); 240*05b00f60SXin Li open(ERROROUT, ">" . $stderrlog); 241*05b00f60SXin Li while(<ERRORRAW>) { 242*05b00f60SXin Li next if /^$/; # blank lines are boring 243*05b00f60SXin Li if(/^(reading from file )(.*)(,.*)$/) { 244*05b00f60SXin Li my $filename = basename($2); 245*05b00f60SXin Li print ERROROUT "${1}${filename}${3}\n"; 246*05b00f60SXin Li next; 247*05b00f60SXin Li } 248*05b00f60SXin Li print ERROROUT; 249*05b00f60SXin Li $linecount++; 250*05b00f60SXin Li } 251*05b00f60SXin Li close(ERROROUT); 252*05b00f60SXin Li close(ERRORRAW); 253*05b00f60SXin Li 254*05b00f60SXin Li if ( -f "$output.stderr" ) { 255*05b00f60SXin Li # 256*05b00f60SXin Li # Compare the standard error with what we think it should be. 257*05b00f60SXin Li # 258*05b00f60SXin Li if ($^O eq 'MSWin32') { 259*05b00f60SXin Li my $winoutput = File::Spec->canonpath($output); 260*05b00f60SXin Li my $canonstderrlog = File::Spec->canonpath($stderrlog); 261*05b00f60SXin Li $nr = system "fc /lb1000 /t /1 $winoutput.stderr $canonstderrlog >tests\DIFF\$outputbase.stderr.diff"; 262*05b00f60SXin Li $errdiffstat = $nr >> 8; 263*05b00f60SXin Li } else { 264*05b00f60SXin Li $nr = system "diff $output.stderr $stderrlog >tests/DIFF/$outputbase.stderr.diff"; 265*05b00f60SXin Li $errdiffstat = WEXITSTATUS($nr); 266*05b00f60SXin Li } 267*05b00f60SXin Li if($r == 0) { 268*05b00f60SXin Li $r = $nr; 269*05b00f60SXin Li } 270*05b00f60SXin Li } 271*05b00f60SXin Li 272*05b00f60SXin Li if($r == 0) { 273*05b00f60SXin Li if($linecount == 0 && $status == 0) { 274*05b00f60SXin Li unlink($stderrlog); 275*05b00f60SXin Li } else { 276*05b00f60SXin Li $errdiffstat = 1; 277*05b00f60SXin Li } 278*05b00f60SXin Li } 279*05b00f60SXin Li 280*05b00f60SXin Li #print sprintf("END: %08x\n", $r); 281*05b00f60SXin Li 282*05b00f60SXin Li if($r == 0) { 283*05b00f60SXin Li if($linecount == 0) { 284*05b00f60SXin Li printf " %-40s: passed\n", $name; 285*05b00f60SXin Li } else { 286*05b00f60SXin Li printf " %-40s: passed with error messages:\n", $name; 287*05b00f60SXin Li showfile($stderrlog); 288*05b00f60SXin Li } 289*05b00f60SXin Li unlink "tests/DIFF/$outputbase.diff"; 290*05b00f60SXin Li return 0; 291*05b00f60SXin Li } 292*05b00f60SXin Li # must have failed! 293*05b00f60SXin Li printf " %-40s: TEST FAILED(exit core=%d/diffstat=%d,%d/r=%d)", $name, $coredump, $diffstat, $errdiffstat, $r; 294*05b00f60SXin Li open FOUT, '>>tests/failure-outputs.txt'; 295*05b00f60SXin Li printf FOUT "\nFailed test: $name\n\n"; 296*05b00f60SXin Li close FOUT; 297*05b00f60SXin Li if(-f "tests/DIFF/$outputbase.diff") { 298*05b00f60SXin Li # 299*05b00f60SXin Li # XXX - just do this directly in Perl? 300*05b00f60SXin Li # 301*05b00f60SXin Li if ($^O eq 'MSWin32') { 302*05b00f60SXin Li system "type tests\\DIFF\\$outputbase.diff >> tests\\failure-outputs.txt"; 303*05b00f60SXin Li } else { 304*05b00f60SXin Li system "cat tests/DIFF/$outputbase.diff >> tests/failure-outputs.txt"; 305*05b00f60SXin Li } 306*05b00f60SXin Li } 307*05b00f60SXin Li 308*05b00f60SXin Li if($r == -1) { 309*05b00f60SXin Li print " (failed to execute: $!)\n"; 310*05b00f60SXin Li return(30); 311*05b00f60SXin Li } 312*05b00f60SXin Li 313*05b00f60SXin Li # this is not working right, $r == 0x8b00 when there is a core dump. 314*05b00f60SXin Li # clearly, we need some platform specific perl magic to take this apart, so look for "core" 315*05b00f60SXin Li # too. 316*05b00f60SXin Li # In particular, on Solaris 10 SPARC an alignment problem results in SIGILL, 317*05b00f60SXin Li # a core dump and $r set to 0x00008a00 ($? == 138 in the shell). 318*05b00f60SXin Li if($r & 127 || -f "core") { 319*05b00f60SXin Li my $with = ($r & 128) ? 'with' : 'without'; 320*05b00f60SXin Li if(-f "core") { 321*05b00f60SXin Li $with = "with"; 322*05b00f60SXin Li } 323*05b00f60SXin Li printf " (terminated with signal %u, %s coredump)", ($r & 127), $with; 324*05b00f60SXin Li if($linecount == 0) { 325*05b00f60SXin Li print "\n"; 326*05b00f60SXin Li } else { 327*05b00f60SXin Li print " with error messages:\n"; 328*05b00f60SXin Li showfile($stderrlog); 329*05b00f60SXin Li } 330*05b00f60SXin Li return(($r & 128) ? 10 : 20); 331*05b00f60SXin Li } 332*05b00f60SXin Li if($linecount == 0) { 333*05b00f60SXin Li print "\n"; 334*05b00f60SXin Li } else { 335*05b00f60SXin Li print " with error messages:\n"; 336*05b00f60SXin Li showfile($stderrlog); 337*05b00f60SXin Li } 338*05b00f60SXin Li return(5); 339*05b00f60SXin Li} 340*05b00f60SXin Li 341*05b00f60SXin Lisub loadconfighash { 342*05b00f60SXin Li if(defined($confighhash)) { 343*05b00f60SXin Li return $confighhash; 344*05b00f60SXin Li } 345*05b00f60SXin Li 346*05b00f60SXin Li $main::confighhash = {}; 347*05b00f60SXin Li 348*05b00f60SXin Li # this could be loaded once perhaps. 349*05b00f60SXin Li open(CONFIG_H, "config.h") || die "Can not open config.h: $!\n"; 350*05b00f60SXin Li while(<CONFIG_H>) { 351*05b00f60SXin Li chomp; 352*05b00f60SXin Li if(/^\#define (.*) 1/) { 353*05b00f60SXin Li #print "Setting $1\n"; 354*05b00f60SXin Li $main::confighhash->{$1} = 1; 355*05b00f60SXin Li } 356*05b00f60SXin Li } 357*05b00f60SXin Li close(CONFIG_H); 358*05b00f60SXin Li #print Dumper($main::confighhash); 359*05b00f60SXin Li 360*05b00f60SXin Li # also run tcpdump --fp-type to get the type of floating-point 361*05b00f60SXin Li # arithmetic we're doing, setting a HAVE_{fptype} key based 362*05b00f60SXin Li # on the value it prints 363*05b00f60SXin Li open(FPTYPE_PIPE, "$TCPDUMP --fp-type |") or die("piping tcpdump --fp-type failed\n"); 364*05b00f60SXin Li my $fptype_val = <FPTYPE_PIPE>; 365*05b00f60SXin Li close(FPTYPE_PIPE); 366*05b00f60SXin Li my $have_fptype; 367*05b00f60SXin Li if($fptype_val == "9877.895") { 368*05b00f60SXin Li $have_fptype = "HAVE_FPTYPE1"; 369*05b00f60SXin Li } else { 370*05b00f60SXin Li $have_fptype = "HAVE_FPTYPE2"; 371*05b00f60SXin Li } 372*05b00f60SXin Li $main::confighhash->{$have_fptype} = 1; 373*05b00f60SXin Li 374*05b00f60SXin Li # and check whether this is OpenBSD, as one test fails in OpenBSD 375*05b00f60SXin Li # due to the sad hellscape of low-numbered DLT_ values, due to 376*05b00f60SXin Li # 12 meaning "OpenBSD loopback" rather than "raw IP" on OpenBSD 377*05b00f60SXin Li if($^O eq "openbsd") { 378*05b00f60SXin Li $main::confighhash->{"IS_OPENBSD"} = 1; 379*05b00f60SXin Li } 380*05b00f60SXin Li 381*05b00f60SXin Li return $main::confighhash; 382*05b00f60SXin Li} 383*05b00f60SXin Li 384*05b00f60SXin Li 385*05b00f60SXin Lisub runOneComplexTest { 386*05b00f60SXin Li local($testconfig) = @_; 387*05b00f60SXin Li 388*05b00f60SXin Li my $output = $testconfig->{output}; 389*05b00f60SXin Li my $input = $testconfig->{input}; 390*05b00f60SXin Li my $name = $testconfig->{name}; 391*05b00f60SXin Li my $options= $testconfig->{args}; 392*05b00f60SXin Li my $foundit = 1; 393*05b00f60SXin Li my $unfoundit=1; 394*05b00f60SXin Li 395*05b00f60SXin Li my $configset = $testconfig->{config_set}; 396*05b00f60SXin Li my $configunset = $testconfig->{config_unset}; 397*05b00f60SXin Li my $ch = loadconfighash(); 398*05b00f60SXin Li #print Dumper($ch); 399*05b00f60SXin Li 400*05b00f60SXin Li if(defined($configset)) { 401*05b00f60SXin Li $foundit = ($ch->{$configset} == 1); 402*05b00f60SXin Li } 403*05b00f60SXin Li if(defined($configunset)) { 404*05b00f60SXin Li $unfoundit=($ch->{$configunset} != 1); 405*05b00f60SXin Li } 406*05b00f60SXin Li 407*05b00f60SXin Li if(!$foundit) { 408*05b00f60SXin Li printf " %-40s: skipped (%s not set)\n", $name, $configset; 409*05b00f60SXin Li return 0; 410*05b00f60SXin Li } 411*05b00f60SXin Li 412*05b00f60SXin Li if(!$unfoundit) { 413*05b00f60SXin Li printf " %-40s: skipped (%s set)\n", $name, $configunset; 414*05b00f60SXin Li return 0; 415*05b00f60SXin Li } 416*05b00f60SXin Li 417*05b00f60SXin Li #use Data::Dumper; 418*05b00f60SXin Li #print Dumper($testconfig); 419*05b00f60SXin Li 420*05b00f60SXin Li # EXPAND any occurrences of @TESTDIR@ to $testsdir 421*05b00f60SXin Li $options =~ s/\@TESTDIR\@/$testsdir/; 422*05b00f60SXin Li 423*05b00f60SXin Li my $result = runtest($name, 424*05b00f60SXin Li $testsdir . "/" . $input, 425*05b00f60SXin Li $testsdir . "/" . $output, 426*05b00f60SXin Li $options); 427*05b00f60SXin Li 428*05b00f60SXin Li if($result == 0) { 429*05b00f60SXin Li $passedcount++; 430*05b00f60SXin Li } else { 431*05b00f60SXin Li $failedcount++; 432*05b00f60SXin Li } 433*05b00f60SXin Li} 434*05b00f60SXin Li 435*05b00f60SXin Li# *.tests files are PERL hash definitions. They should create an array of hashes 436*05b00f60SXin Li# one per test, and place it into the variable @testlist. 437*05b00f60SXin Lisub runComplexTests { 438*05b00f60SXin Li my @files = glob( $testsdir . '/*.tests' ); 439*05b00f60SXin Li foreach $file (@files) { 440*05b00f60SXin Li my @testlist = undef; 441*05b00f60SXin Li my $definitions; 442*05b00f60SXin Li print "FILE: ${file}\n"; 443*05b00f60SXin Li open(FILE, "<".$file) || die "can not open $file: $!"; 444*05b00f60SXin Li { 445*05b00f60SXin Li local $/ = undef; 446*05b00f60SXin Li $definitions = <FILE>; 447*05b00f60SXin Li } 448*05b00f60SXin Li close(FILE); 449*05b00f60SXin Li #print "STUFF: ${definitions}\n"; 450*05b00f60SXin Li eval $definitions; 451*05b00f60SXin Li if(defined($testlist)) { 452*05b00f60SXin Li #use Data::Dumper; 453*05b00f60SXin Li #print Dumper($testlist); 454*05b00f60SXin Li foreach $test (@$testlist) { 455*05b00f60SXin Li runOneComplexTest($test); 456*05b00f60SXin Li } 457*05b00f60SXin Li } else { 458*05b00f60SXin Li warn "File: ${file} could not be loaded as PERL: $!"; 459*05b00f60SXin Li } 460*05b00f60SXin Li } 461*05b00f60SXin Li} 462*05b00f60SXin Li 463*05b00f60SXin Lisub runSimpleTests { 464*05b00f60SXin Li 465*05b00f60SXin Li local($only)=@_; 466*05b00f60SXin Li 467*05b00f60SXin Li open(TESTLIST, "<" . "${testsdir}/TESTLIST") || die "no ${testsdir}/TESTFILE: $!\n"; 468*05b00f60SXin Li while(<TESTLIST>) { 469*05b00f60SXin Li next if /^\#/; 470*05b00f60SXin Li next if /^$/; 471*05b00f60SXin Li 472*05b00f60SXin Li unlink("core"); 473*05b00f60SXin Li ($name, $input, $output, @options) = split; 474*05b00f60SXin Li #print "processing ${only} vs ${name}\n"; 475*05b00f60SXin Li next if(defined($only) && $only ne $name); 476*05b00f60SXin Li 477*05b00f60SXin Li my $options = join(" ", @options); 478*05b00f60SXin Li #print "@{options} becomes ${options}\n"; 479*05b00f60SXin Li 480*05b00f60SXin Li my $hash = { name => $name, 481*05b00f60SXin Li input=> $input, 482*05b00f60SXin Li output=>$output, 483*05b00f60SXin Li args => $options }; 484*05b00f60SXin Li 485*05b00f60SXin Li runOneComplexTest($hash); 486*05b00f60SXin Li } 487*05b00f60SXin Li} 488*05b00f60SXin Li 489*05b00f60SXin Liif(scalar(@ARGV) == 0) { 490*05b00f60SXin Li runSimpleTests(); 491*05b00f60SXin Li runComplexTests(); 492*05b00f60SXin Li} else { 493*05b00f60SXin Li runSimpleTests($ARGV[0]); 494*05b00f60SXin Li} 495*05b00f60SXin Li 496*05b00f60SXin Li# exit with number of failing tests. 497*05b00f60SXin Liprint "------------------------------------------------\n"; 498*05b00f60SXin Liprintf("%4u tests failed\n",$failedcount); 499*05b00f60SXin Liprintf("%4u tests passed\n",$passedcount); 500*05b00f60SXin Li 501*05b00f60SXin Lishowfile(${failureoutput}); 502*05b00f60SXin Liexit $failedcount; 503