#!/usr/bin/env perl $TCPDUMP = "./tcpdump"; if ($^O eq 'MSWin32') { $TCPDUMP = "windump"; } if($ENV{TCPDUMP_BIN}) { $TCPDUMP = $ENV{TCPDUMP_BIN}; } use File::Basename; use POSIX qw( WEXITSTATUS WIFEXITED); system("mkdir -p tests/NEW tests/DIFF"); if(@ARGV != 4) { print "Usage: TESTonce name input output options\n"; exit 20; } $name=$ARGV[0]; $input=$ARGV[1]; $output=$ARGV[2]; $options=$ARGV[3]; my $r; my $debug = 0; # change to suit. $outputbase = basename($output); my $coredump = false; my $status = 0; my $linecount = 0; my $rawstderrlog = "tests/NEW/${outputbase}.raw.stderr"; my $stderrlog = "tests/NEW/${outputbase}.stderr"; my $diffstat = 0; my $errdiffstat = 0; my $cmd; if ($^O eq 'MSWin32') { $r = system ".\\${TCPDUMP} -t -n -r $input $options 2>NUL | sed 's/\\r//' | tee tests/NEW/${outputbase} | diff $output - >tests/DIFF/${outputbase}.diff"; # need to do same as below for Cygwin. } else { # we used to do this as a nice pipeline, but the problem is that $r fails to # to be set properly if the tcpdump core dumps. $cmd = "$TCPDUMP 2>${rawstderrlog} -t -n -r $input $options >tests/NEW/${outputbase}"; print "CMD: $cmd\n" if $debug; $r = system $cmd; if($r == -1) { # failed to start due to error. $status = $!; } if($r != 0) { $coredump = false; $status = 0; # this means tcpdump failed, which however, might be expected. open(OUTPUT, ">>"."tests/NEW/${outputbase}") || die "fail to open ${outputbase}\n"; if( $r & 128 ) { $coredump = $r & 127; } if( WIFEXITED($r)) { $status = WEXITSTATUS($r); } if($coredump || $status) { printf OUTPUT "\nEXIT CODE %08x: dump:%d code: %d\n", $r, $coredump, $status; } else { printf OUTPUT "\nEXIT CODE %08x\n", $r; } close(OUTPUT); $r = 0; # clear the error so that the diff will occur. } print "RUNNING DIFF after ${r}\n" if $debug; # always run diff. $cmd = "cat tests/NEW/${outputbase} | diff $output - >tests/DIFF/${outputbase}.diff"; print "RUNNING: $cmd\n" if $debug; $r = system $cmd; if(WIFEXITED($r)) { $diffstat = WEXITSTATUS($r); } #system("/bin/sh"); # process the file, sanitize "reading from" line, and count lines $linecount = 0; open(ERRORRAW, "<" . $rawstderrlog); open(ERROROUT, ">" . $stderrlog); while() { next if /^\s*$/; # blank lines are boring if(/^(reading from file )(.*)(,.*)$/) { my $filename = basename($2); print ERROROUT "${1}${filename}${3}\n"; next; } print ERROROUT; $linecount++; } close(ERROROUT); close(ERRORRAW); if ( -f "$output.stderr" ) { $nr = system "cat $stderrlog | diff $output.stderr - >tests/DIFF/$outputbase.stderr.diff"; if($r == 0) { $r = $nr; } $errdiffstat = WEXITSTATUS($nr); } else { $errdiffstat = "-" } if($r == 0) { if($linecount == 0 && $status == 0) { print "UNLINK: ${stderrlog}\n" if $debug; unlink($stderrlog) unless $debug; } else { $errdiffstat = "+"; } } print sprintf("END: %08x\n", $r) if $debug; } if($r == 0) { my $stderrlog=""; if($linecount > 0 && $errdiffstat != "-") { $stderrlog=sprintf("-- %d lines extra in stderr", $linecount); } if(!defined($ENV{"SKIPPASSED"})) { printf " %-35s: passed%s\n", $name, $stderrlog; } unlink "tests/DIFF/$outputbase.diff" unless $debug; exit 0; } # must have failed! printf " %-35s: TEST FAILED(exit core=%d/diffstat=%d,%d/r=%d)", $name, $coredump, $diffstat, $errdiffstat, $r; open FOUT, '>>tests/failure-outputs.txt'; printf FOUT "\nFailed test: $name\n\n"; close FOUT; if(-f "tests/DIFF/$outputbase.diff") { system "cat tests/DIFF/$outputbase.diff >> tests/failure-outputs.txt"; } if($r == -1) { print " (failed to execute: $!)\n"; exit 30; } # this is not working right, $r == 0x8b00 when there is a core dump. # clearly, we need some platform specific perl magic to take this apart, so look for "core" # too. # In particular, on Solaris 10 SPARC an alignment problem results in SIGILL, # a core dump and $r set to 0x00008a00 ($? == 138 in the shell). if($r & 127 || -f "core") { my $with = ($r & 128) ? 'with' : 'without'; if(-f "core") { $with = "with"; } printf " (terminated with signal %u, %s coredump)\n", ($r & 127), $with; exit ($r & 128) ? 10 : 20; } print "\n"; exit $r >> 8;