]> mj.ucw.cz Git - libucw.git/commitdiff
A new unit test module.
authorMartin Mares <mj@ucw.cz>
Sun, 18 Nov 2007 18:33:08 +0000 (19:33 +0100)
committerMartin Mares <mj@ucw.cz>
Sun, 18 Nov 2007 18:33:08 +0000 (19:33 +0100)
Explicit input and output files can be defined now, the expected
exit code of the process can be set and, last but not least, test
cases can be named to simplify orientation in long test suites.

The `run' directory is no longer hard-wired, the tester now accepts
--verbose and --rundir switches.

The makefiles now pass --rundir=run and also $TESTERFLAGS, allowing
to turn on the verbose mode at request.

build/Makebottom
build/tester

index bf342b0cea618849897f0c1bc82a8e8cd829dad8..a474614bb2817c9f93e6310c22b347d443a83269 100644 (file)
@@ -126,7 +126,7 @@ $(o)/%-t: $(o)/%-tt.o $(TESTING_DEPS)
 
 $(o)/%.test: $(s)/%.t $(s)/build/tester
        $(M)TEST $@
-       $(Q)$(s)/build/tester $< && touch $@
+       $(Q)$(s)/build/tester --rundir=run $(TESTERFLAGS) $< && touch $@
 
 # Rules for binaries
 
index 73794d9396b818711c0e70854d627ab16b31e848..fd6cce3fcd620b886260d7178828793b921c1bd8 100755 (executable)
@@ -1,8 +1,32 @@
 #!/usr/bin/perl
 # A simple unit testing script
-# (c) 2004 Martin Mares <mj@ucw.cz>
+# (c) 2004--2007 Martin Mares <mj@ucw.cz>
 # (c) 2007 Pavel Charvat <pchar@ucw.cz>
 
+# Tests in the test file have a syntax similar to mail headers,
+# individual test case are separated by blank lines and they can contain
+# the following fields:
+#
+#      Name:   name of the case (default: sequence number since start of file)
+#      Run:    command to run (default: command from the previous test case)
+#              This can be an arbitrary shell pipeline, sequences $0 to $9 are
+#              replaced by file names of In<N> or Out<N> files (see below).
+#      In:     lines to pass to the program as standard input
+#      Out:    lines to expect at the program's standard output
+#      In<N>:  lines to pass to the program as input file <N>
+#      Out<N>: lines to expect from the program in output file <N>
+#              Both In<N> and Out<N> can be specified simultaneously if we
+#              are testing a program which modifies some of its input files.
+#      Exit:   expected exit code of the program (default: 0)
+
+use Getopt::Long;
+
+my $verbose = 0;
+my $rundir = ".";
+GetOptions("verbose!" => \$verbose,
+          "rundir=s" => \$rundir)
+       or die "Usage: tester [--verbose] [--rundir=<dir>] <tests>\n";
+
 my @tests = ();
 my $tt;
 my $append_to;
@@ -30,50 +54,88 @@ while (<>) {
 my $i = 0;
 my $errors = 0;
 my $prev_run = undef;
-foreach $tt (@tests) {
+TEST: foreach $tt (@tests) {
        $i++;
-       print "Test $i: ";
+       my $name = $tt->{'Name'} || $i;
+       print "Test $name: ";
        $run = ($tt->{'Run'} || $prev_run) or die "Don't know what to run";
        $prev_run = $run;
-       my ($ifi, $ofi);
+
+       my @out_files = ();
+       my @out_checks = ();
+       my @temps = ();
+       my $redirs = "";
+
        if (defined $tt->{'In'}) {
-               $ifi = "tmp/test$i.in";
-               open X, ">run/$ifi" or die "Unable to create $ifi";
+               my $ifi = "tmp/test$i.in";
+               open X, ">$rundir/$ifi" or die "Unable to create $ifi";
                print X $tt->{'In'}, "\n";
                close X;
-               $run .= " <$ifi";
+               $redirs .= " <$ifi";
+               push @temps, $ifi;
        } else {
-               $run .= " </dev/null";
+               $redirs .= " </dev/null";
        }
        if (defined $tt->{'Out'}) {
-               $ofi = "tmp/test$i.out";
-               unlink "run/$ofi";
-               $run .= " >$ofi";
+               my $ofi = "tmp/test$i.out";
+               unlink "$rundir/$ofi";
+               $redirs .= " >$ofi";
+               push @temps, $ofi;
+               push @out_files, $ofi;
+               push @out_checks, $tt->{'Out'};
        } else {
-               $run .= " >/dev/null";
+               $redirs .= " >/dev/null";
+       }
+       foreach my $arg (0..9) {
+               my $f = "tmp/test$i.$arg";
+               if (defined $tt->{"Out$arg"}) {
+                       unlink "$rundir/$f";
+                       push @temps, $f;
+                       push @out_files, $f;
+                       push @out_checks, $tt->{"Out$arg"};
+               }
+               if (defined $tt->{"In$arg"}) {
+                       open X, ">$rundir/$f" or die "Unable to create $f";
+                       print X $tt->{"In$arg"}, "\n";
+                       close X;
+                       push @temps, $f;
+               }
        }
-       system "cd run && ( $run )";
-       if ($?) {
-               print "FAILED with exit code $?\n";
+       $run =~ s/\$(\d)/tmp\/test$i.$1/g;
+       print "(running $run) " if $verbose;
+       system "cd $rundir && ( $run ) $redirs";
+       if ($? % 256) {
+               print "FAILED with status code $?\n";
                $errors++;
                next;
        }
-       if (defined $tt->{'Out'}) {
-               open X, "<run/$ofi" or die "Unable to read $ofi";
+       my $ec = $? / 256;
+       my $expect_ec = $tt->{'Exit'} || 0;
+       if ($ec != $expect_ec) {
+               print "FAILED: unexpected exit code $ec\n";
+               $errors++;
+               next;
+       }
+
+       for (my $i=0; $i<=$#out_files; $i++) {
+               my $ofi = $out_files[$i];
+               open X, "<$rundir/$ofi" or die "Unable to read $ofi";
                my $out;
                {
                        local $/ = undef;
                        $out = <X>;
                }
                close X;
-               if ($out ne $tt->{'Out'} . "\n") {
+               if ($out ne $out_checks[$i] . "\n") {
                        print "FAILED (see $ofi)\n";
                        $errors++;
-                       next;
+                       next TEST;
                }
        }
-       unlink $ifi if $ifi;
-       unlink $ofi if $ofi;
+
+       foreach my $f (@temps) {
+               unlink "$rundir/$f";
+       }
        print "OK\n";
 }