X-Git-Url: http://mj.ucw.cz/gitweb/?a=blobdiff_plain;f=build%2Ftester;h=6a827b194ffcacbe08829bde52ed189636fb7050;hb=0db6e10eac28f38bfc3b325b13ad95107c58ce1e;hp=a9bdfd60f7de2f2c350942917361814b7e605dd0;hpb=45272d09316ecfba01f10e1968bd6f9a921909d2;p=libucw.git diff --git a/build/tester b/build/tester index a9bdfd60..6a827b19 100755 --- a/build/tester +++ b/build/tester @@ -1,6 +1,40 @@ #!/usr/bin/perl # A simple unit testing script -# (c) 2004 Martin Mares +# (c) 2004--2013 Martin Mares +# (c) 2007 Pavel Charvat + +# 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 or Out files (see below). +# In: lines to pass to the program as standard input +# Out: lines to expect at the program's standard output +# Err: lines to expect at the program's standard error output +# In: lines to pass to the program as input file +# Out: lines to expect from the program in output file +# Both In and Out 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) +# +# A value of a field can be optionally given as a shell-style here-document: +# +# In < \$verbose, + "rundir=s" => \$rundir) + or die "Usage: tester [--verbose] [--rundir=] \n"; my @tests = (); my $tt; @@ -21,58 +55,115 @@ while (<>) { ($tt->{$n}) && die "$n already defined"; $tt->{$n} = $v; $append_to = \($tt->{$n}); + } elsif (my ($n,$sep) = /^(\w+)\s*<<(\w+)\s*$/) { + if (!$tt) { + $tt = {}; + push @tests, $tt; + } + ($tt->{$n}) && die "$n already defined"; + $tt->{$n} = ""; + $sep .= "\n"; + while (1) { + my $line = <>; + defined $line or die "Here-document not terminated"; + last if $line eq $sep; + $tt->{$n} .= $line; + } } else { die "Test script syntax error"; } } +if (! -d "$rundir/tmp") { + mkdir "$rundir/tmp" or die "Unable to create $rundir/tmp: $!"; +} + 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 $redirs = ""; + if (defined $tt->{'In'}) { - $ifi = "run/tmp/test$i.in"; - open X, ">$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"; } else { - $run .= " {'Out'}) { - $ofi = "run/tmp/test$i.out"; - unlink $ofi; - $run .= " >$ofi"; + my $ofi = "tmp/test$i.out"; + unlink "$rundir/$ofi"; + $redirs .= " >$ofi"; + push @out_files, $ofi; + push @out_checks, $tt->{'Out'}; } else { - $run .= " >/dev/null"; + $redirs .= " >/dev/null"; + } + if (defined $tt->{'Err'}) { + my $efi = "tmp/test$i.err"; + unlink "$rundir/$efi"; + $redirs .= " 2>$efi"; + push @out_files, $efi; + push @out_checks, $tt->{'Err'}; + } + foreach my $arg (0..9) { + my $f = "tmp/test$i.$arg"; + if (defined $tt->{"Out$arg"}) { + unlink "$rundir/$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; + } } - `$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, "<$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 = ; } close X; - if ($out ne $tt->{'Out'} . "\n") { + $out =~ /\n$/s or $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; + + system "rm -f $rundir/tmp/test$i.*"; print "OK\n"; }