xref: /aosp_15_r20/external/tcpdump/tests/TESTrun (revision 05b00f6010a2396e3db2409989fc67270046269f)
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